/[smeserver]/cdrom.image/updates/bootloaderInfo.py
ViewVC logotype

Contents of /cdrom.image/updates/bootloaderInfo.py

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (show annotations) (download) (as text)
Wed Apr 5 01:20:27 2006 UTC (18 years, 8 months ago) by slords
Branch: MAIN
Changes since 1.4: +177 -115 lines
Content type: text/x-python
Update anaconda to be in sync with 4.3 and FC4

1 #
2 # bootloaderInfo.py - bootloader config object used in creation of new
3 # bootloader configs. Originally from anaconda
4 #
5 # Jeremy Katz <katzj@redhat.com>
6 # Erik Troan <ewt@redhat.com>
7 # Peter Jones <pjones@redhat.com>
8 #
9 # Copyright 2005 Red Hat, Inc.
10 #
11 # This software may be freely redistributed under the terms of the GNU
12 # library public license.
13 #
14 # You should have received a copy of the GNU Library Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 #
18
19 import isys
20 import os, sys
21 import crypt
22 import random
23 import butil
24 import string
25
26 from lilo import LiloConfigFile
27 from rhpl.log import log
28 from rhpl.translate import _, N_
29 import rhpl.executil
30
31 import booty
32 import checkbootloader
33
34 dosFilesystems = ('FAT', 'fat16', 'fat32', 'ntfs', 'hpfs')
35
36 if os.path.exists('edd'):
37 sys.path.append('edd/')
38 else:
39 sys.path.append('/usr/lib/bootloader')
40
41 if butil.getArch() == "i386":
42 import edd
43
44 def doesDualBoot():
45 if butil.getArch() == "i386" or butil.getArch() == "x86_64":
46 return 1
47 return 0
48
49 # hack and a half
50 # there's no guarantee that data is written to the disk and grub
51 # reads both the filesystem and the disk. suck.
52 def syncDataToDisk(dev, mntpt, instRoot = "/"):
53 import isys, fsset
54 isys.sync()
55 isys.sync()
56 isys.sync()
57
58 # and xfs is even more "special" (#117968)
59 if fsset.isValidXFS(dev):
60 rhpl.executil.execWithRedirect( "/usr/sbin/xfs_freeze",
61 ["/usr/sbin/xfs_freeze", "-f", mntpt],
62 stdout = "/dev/tty5",
63 stderr = "/dev/tty5",
64 root = instRoot)
65 rhpl.executil.execWithRedirect( "/usr/sbin/xfs_freeze",
66 ["/usr/sbin/xfs_freeze", "-u", mntpt],
67 stdout = "/dev/tty5",
68 stderr = "/dev/tty5",
69 root = instRoot)
70
71 class BootyNoKernelWarning:
72 def __init__ (self, value=""):
73 self.value = value
74
75 def __str__ (self):
76 return self.value
77
78 class KernelArguments:
79
80 def get(self):
81 return self.args
82
83 def set(self, args):
84 self.args = args
85
86 def chandevget(self):
87 return self.cargs
88
89 def chandevset(self, args):
90 self.cargs = args
91
92 def append(self, args):
93 if self.args:
94 # don't duplicate the addition of an argument (#128492)
95 if self.args.find(args) != -1:
96 return
97 self.args = self.args + " "
98 self.args = self.args + "%s" % (args,)
99
100
101 def __init__(self):
102 str = ""
103
104 if butil.getArch() == "s390":
105 self.cargs = []
106 f = open("/tmp/install.cfg")
107 lines = f.readlines()
108 for line in lines:
109 try:
110 (vname,vparm) = line.split('=', 1)
111 vname = vname.strip()
112 vparm = vparm.replace('"','')
113 vparm = vparm.strip()
114 if vname == "DASD":
115 str = str + "dasd=" + vparm
116 if vname == "CHANDEV":
117 self.cargs.append(vparm)
118 if vname == "QETHPARM":
119 self.cargs.append(vparm)
120 except Exception, e:
121 pass
122
123 # look for kernel arguments we know should be preserved and add them
124 ourargs = ["speakup_synth=", "apic", "noapic", "apm=", "ide=nodma", "noht", "acpi=", "video="]
125 f = open("/proc/cmdline")
126 cmdline = f.read()[:-1]
127 f.close()
128 cmdlineargs = cmdline.split(" ")
129 for arg in cmdlineargs:
130 for check in ourargs:
131 if arg.startswith(check):
132 if str: str = str + " "
133 str = str + arg
134
135 self.args = str
136
137 class BootImages:
138 # returns dictionary of (label, longlabel, devtype) pairs indexed by device
139 def getImages(self):
140 # return a copy so users can modify it w/o affecting us
141
142 dict = {}
143 for key in self.images.keys():
144 dict[key] = self.images[key]
145
146 return dict
147
148 def setImageLabel(self, dev, label, setLong = 0):
149 if setLong:
150 self.images[dev] = (self.images[dev][0], label,
151 self.images[dev][2])
152 else:
153 self.images[dev] = (label, self.images[dev][1],
154 self.images[dev][2])
155
156
157 # default is a device
158 def setDefault(self, default):
159 self.default = default
160
161 def getDefault(self):
162 return self.default
163
164 # XXX this has internal anaconda-ish knowledge. ick
165 def setup(self, diskSet, fsset):
166 devices = {}
167 devs = self.availableBootDevices(diskSet, fsset)
168 for (dev, type) in devs:
169 devices[dev] = 1
170
171 # These partitions have disappeared
172 for dev in self.images.keys():
173 if not devices.has_key(dev): del self.images[dev]
174
175 # These have appeared
176 for (dev, type) in devs:
177 if not self.images.has_key(dev):
178 if type in dosFilesystems and doesDualBoot():
179 self.images[dev] = ("Other", "Other", type)
180 elif type in ("hfs", "hfs+") and butil.getPPCMachine() == "PMac":
181 self.images[dev] = ("Other", "Other", type)
182 else:
183 self.images[dev] = (None, None, type)
184
185
186 if not self.images.has_key(self.default):
187 entry = fsset.getEntryByMountPoint('/')
188 self.default = entry.device.getDevice()
189 (label, longlabel, type) = self.images[self.default]
190 if not label:
191 self.images[self.default] = ("linux",
192 butil.getProductName(), type)
193
194 # XXX more internal anaconda knowledge
195 def availableBootDevices(self, diskSet, fsset):
196 devs = []
197 foundDos = 0
198 for (dev, type) in diskSet.partitionTypes():
199 if type in dosFilesystems and not foundDos and doesDualBoot():
200 import isys
201 import partedUtils
202
203 isys.makeDevInode(dev, '/tmp/' + dev)
204 part = partedUtils.get_partition_by_name(diskSet.disks, dev)
205 if part.native_type not in partedUtils.dosPartitionTypes:
206 continue
207
208 try:
209 bootable = isys.checkBoot('/tmp/' + dev)
210 devs.append((dev, type))
211 foundDos = 1
212 except Exception, e:
213 log("exception checking %s: %s" %(dev, e))
214 pass
215 elif ((type == 'ntfs' or type =='hpfs') and not foundDos
216 and doesDualBoot()):
217 devs.append((dev, type))
218 # maybe questionable, but the first ntfs or fat is likely to
219 # be the correct one to boot with XP using ntfs
220 foundDos = 1
221 elif type in ('hfs', 'hfs+') and butil.getPPCMachine() == "PMac":
222 import isys
223 import partedUtils
224
225 part = partedUtils.get_partition_by_name(diskSet.disks, dev)
226 if partedUtils.get_flags(part) != "boot":
227 devs.append((dev, type))
228
229 slash = fsset.getEntryByMountPoint('/')
230 if not slash or not slash.device or not slash.fsystem:
231 raise ValueError, ("Trying to pick boot devices but do not have a "
232 "sane root partition. Aborting install.")
233 devs.append((slash.device.getDevice(), slash.fsystem.getName()))
234
235 devs.sort()
236
237 return devs
238
239
240
241 def __init__(self):
242 self.default = None
243 self.images = {}
244
245
246 class bootloaderInfo:
247 def setUseGrub(self, val):
248 pass
249
250 def useGrub(self):
251 return self.useGrubVal
252
253 def setForceLBA(self, val):
254 pass
255
256 def setPassword(self, val, isCrypted = 1):
257 pass
258
259 def getPassword(self):
260 pass
261
262 def getDevice(self):
263 return self.device
264
265 def setDevice(self, device):
266 self.device = device
267
268 (dev, part) = getDiskPart(device)
269 if part is None:
270 self.defaultDevice = "mbr"
271 else:
272 self.defaultDevice = "partition"
273
274 # XXX need to abstract out the requirement for a fsset to be able
275 # to get it "on the fly" on a running system as well as being able
276 # to get it how we do now from anaconda. probably by having the
277 # first thing in the chain create a "fsset" object that has the
278 # dictionary of mounted filesystems since that's what we care about
279 def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList,
280 chainList, defaultDev):
281 images = bl.images.getImages()
282
283 # on upgrade read in the lilo config file
284 lilo = LiloConfigFile ()
285 self.perms = 0600
286 if os.access (instRoot + self.configfile, os.R_OK):
287 self.perms = os.stat(instRoot + self.configfile)[0] & 0777
288 lilo.read (instRoot + self.configfile)
289 os.rename(instRoot + self.configfile,
290 instRoot + self.configfile + '.rpmsave')
291 # if it's an absolute symlink, just get it out of our way
292 elif (os.path.islink(instRoot + self.configfile) and
293 os.readlink(instRoot + self.configfile)[0] == '/'):
294 os.rename(instRoot + self.configfile,
295 instRoot + self.configfile + '.rpmsave')
296
297 # Remove any invalid entries that are in the file; we probably
298 # just removed those kernels.
299 for label in lilo.listImages():
300 (fsType, sl, path, other) = lilo.getImage(label)
301 if fsType == "other": continue
302
303 if not os.access(instRoot + sl.getPath(), os.R_OK):
304 lilo.delImage(label)
305
306 lilo.addEntry("prompt", replace = 0)
307 lilo.addEntry("timeout", "20", replace = 0)
308
309 rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
310 if not rootDev:
311 raise RuntimeError, "Installing lilo, but there is no root device"
312
313 if rootDev == defaultDev:
314 lilo.addEntry("default", kernelList[0][0])
315 else:
316 lilo.addEntry("default", chainList[0][0])
317
318 for (label, longlabel, version) in kernelList:
319 kernelTag = "-" + version
320 kernelFile = self.kernelLocation + "vmlinuz" + kernelTag
321
322 try:
323 lilo.delImage(label)
324 except IndexError, msg:
325 pass
326
327 sl = LiloConfigFile(imageType = "image", path = kernelFile)
328
329 initrd = booty.makeInitrd (kernelTag, instRoot)
330
331 sl.addEntry("label", label)
332 if os.access (instRoot + initrd, os.R_OK):
333 sl.addEntry("initrd", "%sinitrd%s.img" %(self.kernelLocation,
334 kernelTag))
335
336 sl.addEntry("read-only")
337
338 append = "%s" %(self.args.get(),)
339 realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
340 if not realroot.startswith("LABEL="):
341 sl.addEntry("root", '/dev/' + rootDev)
342 else:
343 if len(append) > 0:
344 append = "%s root=%s" %(append,realroot)
345 else:
346 append = "root=%s" %(realroot,)
347
348 if len(append) > 0:
349 sl.addEntry('append', '"%s"' % (append,))
350
351 lilo.addImage (sl)
352
353 for (label, longlabel, device) in chainList:
354 if ((not label) or (label == "")):
355 continue
356 try:
357 (fsType, sl, path, other) = lilo.getImage(label)
358 lilo.delImage(label)
359 except IndexError:
360 sl = LiloConfigFile(imageType = "other",
361 path = "/dev/%s" %(device))
362 sl.addEntry("optional")
363
364 sl.addEntry("label", label)
365 lilo.addImage (sl)
366
367 # Sanity check #1. There could be aliases in sections which conflict
368 # with the new images we just created. If so, erase those aliases
369 imageNames = {}
370 for label in lilo.listImages():
371 imageNames[label] = 1
372
373 for label in lilo.listImages():
374 (fsType, sl, path, other) = lilo.getImage(label)
375 if sl.testEntry('alias'):
376 alias = sl.getEntry('alias')
377 if imageNames.has_key(alias):
378 sl.delEntry('alias')
379 imageNames[alias] = 1
380
381 # Sanity check #2. If single-key is turned on, go through all of
382 # the image names (including aliases) (we just built the list) and
383 # see if single-key will still work.
384 if lilo.testEntry('single-key'):
385 singleKeys = {}
386 turnOff = 0
387 for label in imageNames.keys():
388 l = label[0]
389 if singleKeys.has_key(l):
390 turnOff = 1
391 singleKeys[l] = 1
392 if turnOff:
393 lilo.delEntry('single-key')
394
395 return lilo
396
397 def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
398 defaultDev, justConfig, intf = None):
399 if len(kernelList) >= 1:
400 config = self.getBootloaderConfig(instRoot, fsset, bl, langs,
401 kernelList, chainList,
402 defaultDev)
403 config.write(instRoot + self.configfile, perms = self.perms)
404 else:
405 self.noKernelsWarn(intf)
406
407 return ""
408
409 # XXX in the future we also should do some validation on the config
410 # file that's already there
411 # XXX concept of the intf isn't very well defined outside of anaconda...
412 # probably should just pass back up an error
413 def noKernelsWarn(self, intf):
414 raise BootyNoKernelWarning
415
416 def getArgList(self):
417 args = []
418
419 if self.defaultDevice is None:
420 args.append("--location=none")
421 return args
422
423 args.append("--location=%s" % (self.defaultDevice,))
424 args.append("--driveorder=%s" % (",".join(self.drivelist)))
425
426 if self.args.get():
427 args.append("--append=\"%s\"" %(self.args.get()))
428
429 return args
430
431 def writeKS(self, f):
432 f.write("bootloader")
433 for arg in self.getArgList():
434 f.write(" " + arg)
435 f.write("\n")
436
437 def createDriveList(self):
438 # create a drive list that we can use for drive mappings
439 # XXX has anaconda internals knowledge
440 import isys
441 import flags
442 drives = isys.hardDriveDict().keys()
443 drives.sort (isys.compareDrives)
444
445 # now filter out all of the removable media unless expert mode
446 rc = []
447 for drive in drives:
448 if not isys.driveIsRemovable(drive) or flags.flags.expert:
449 rc.append(drive)
450 return rc
451
452 def __init__(self):
453 self.args = KernelArguments()
454 self.images = BootImages()
455 self.device = None
456 self.defaultDevice = None # XXX hack, used by kickstart
457 self.useGrubVal = 0 # only used on x86
458 self.configfile = None
459 self.kernelLocation = "/boot/"
460 self.forceLBA32 = 0
461 self.password = None
462 self.pure = None
463 self.above1024 = 0
464
465 # this has somewhat strange semantics. if 0, act like a normal
466 # "install" case. if 1, update lilo.conf (since grubby won't do that)
467 # and then run lilo or grub only.
468 # XXX THIS IS A HACK. implementation details are only there for x86
469 self.doUpgradeOnly = 0
470 self.kickstart = 0
471
472 self.drivelist = self.createDriveList()
473
474 from flags import flags
475 if flags.serial != 0:
476 # now look at /proc/cmdline to pull any serial console
477 # args
478 f = open("/proc/cmdline", "r")
479 cmdline = f.read()[:-1]
480 f.close()
481
482 options = ""
483 device = None
484 cmdlineargs = cmdline.split(" ")
485 for arg in cmdlineargs:
486 # found a console argument
487 if arg.startswith("console="):
488 (foo, console) = arg.split("=")
489 # the options are everything after the comma
490 comma = console.find(",")
491 if comma != -1:
492 options = console[comma:]
493 device = console[:comma]
494 else:
495 options = ""
496 device = console
497
498 if device is None:
499 self.serialDevice = "ttyS0"
500 self.serialOptions = ""
501 else:
502 self.serialDevice = device
503 # don't keep the comma in the options
504 self.serialOptions = options[1:]
505
506 self.args.append("console=%s%s" %(self.serialDevice, options))
507
508 self.serial = 1
509 else:
510 self.serial = 0
511 self.serialDevice = None
512 self.serialOptions = None
513
514 if flags.virtpconsole is not None:
515 if flags.virtpconsole.startswith("/dev/"):
516 con = flags.virtpconsole[5:]
517 else:
518 con = flags.virtpconsole
519 self.args.append("console=%s" %(con,))
520
521
522 class ia64BootloaderInfo(bootloaderInfo):
523 # XXX wouldn't it be nice to have a real interface to use efibootmgr from?
524 def removeOldEfiEntries(self, instRoot):
525 p = os.pipe()
526 rhpl.executil.execWithRedirect('/usr/sbin/efibootmgr', ["efibootmgr"],
527 root = instRoot, stdout = p[1])
528 os.close(p[1])
529
530 c = os.read(p[0], 1)
531 buf = c
532 while (c):
533 c = os.read(p[0], 1)
534 buf = buf + c
535 os.close(p[0])
536 lines = string.split(buf, '\n')
537 for line in lines:
538 fields = string.split(line)
539 if len(fields) < 2:
540 continue
541 if string.join(fields[1:], " ") == butil.getProductName():
542 entry = fields[0][4:8]
543 rhpl.executil.execWithRedirect('/usr/sbin/efibootmgr',
544 ["efibootmgr", "-b", entry, "-B"],
545 root = instRoot,
546 stdout="/dev/tty5", stderr="/dev/tty5")
547
548 def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList,
549 chainList, defaultDev):
550 config = bootloaderInfo.getBootloaderConfig(self, instRoot, fsset,
551 bl, langs,
552 kernelList, chainList,
553 defaultDev)
554 # altix boxes need relocatable (#120851)
555 config.addEntry("relocatable")
556
557 return config
558
559 def writeLilo(self, instRoot, fsset, bl, langs, kernelList,
560 chainList, defaultDev, justConfig):
561 config = self.getBootloaderConfig(instRoot, fsset, bl, langs,
562 kernelList, chainList, defaultDev)
563 config.write(instRoot + self.configfile, perms = self.perms)
564
565 return ""
566
567 def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
568 defaultDev, justConfig, intf):
569 if len(kernelList) >= 1:
570 str = self.writeLilo(instRoot, fsset, bl, langs, kernelList,
571 chainList, defaultDev, justConfig)
572 else:
573 self.noKernelsWarn(intf)
574
575 bootdev = fsset.getEntryByMountPoint("/boot/efi").device.getDevice()
576 if not bootdev:
577 bootdev = fsset.getEntryByDeviceName("sda1").device.getDevice()
578
579 if not os.access(instRoot + "/etc/elilo.conf", os.R_OK):
580 os.symlink("../" + self.configfile, instRoot + "/etc/elilo.conf")
581
582 ind = len(bootdev)
583 try:
584 while (bootdev[ind-1] in string.digits):
585 ind = ind - 1
586 except IndexError:
587 ind = len(bootdev) - 1
588
589 bootdisk = bootdev[:ind]
590 bootpart = bootdev[ind:]
591 if (bootdisk.startswith('ida/') or bootdisk.startswith('cciss/') or
592 bootdisk.startswith('rd/') or bootdisk.startswith('sx8/')):
593 bootdisk = bootdisk[:-1]
594
595 self.removeOldEfiEntries(instRoot)
596
597 argv = [ "/usr/sbin/efibootmgr", "-c" , "-w", "-L",
598 butil.getProductName(), "-d", "/dev/%s" % bootdisk,
599 "-p", bootpart, "-l", "EFI\\redhat\\elilo.efi" ]
600 rhpl.executil.execWithRedirect(argv[0], argv, root = instRoot,
601 stdout = "/dev/tty5",
602 stderr = "/dev/tty5")
603
604
605 def __init__(self):
606 bootloaderInfo.__init__(self)
607 self.useGrubVal = 1
608 self.kernelLocation = ""
609 self.configfile = "/boot/efi/EFI/redhat/elilo.conf"
610
611
612 class x86BootloaderInfo(bootloaderInfo):
613 def setPassword(self, val, isCrypted = 1):
614 if not val:
615 self.password = val
616 self.pure = val
617 return
618
619 if isCrypted and self.useGrubVal == 0:
620 log("requested crypted password with lilo; ignoring")
621 self.pure = None
622 return
623 elif isCrypted:
624 self.password = val
625 self.pure = None
626 else:
627 salt = "$1$"
628 saltLen = 8
629
630 for i in range(saltLen):
631 salt = salt + random.choice (string.letters +
632 string.digits + './')
633
634 self.password = crypt.crypt (val, salt)
635 self.pure = val
636
637 def getPassword (self):
638 return self.pure
639
640 def setForceLBA(self, val):
641 self.forceLBA32 = val
642
643 def setUseGrub(self, val):
644 self.useGrubVal = val
645
646 def getPhysicalDevices(self, device):
647 # This finds a list of devices on which the given device name resides.
648 # Accepted values for "device" are raid1 md devices (i.e. "md0"),
649 # physical disks ("hda"), and real partitions on physical disks
650 # ("hda1"). Volume groups/logical volumes are not accepted.
651 #
652 # XXX this has internal anaconda-ish knowledge. ick.
653 import isys
654 import lvm
655
656 if string.split(device, '/', 1)[0] in map (lambda vg: vg[0],
657 lvm.vglist()):
658 return []
659
660 if device.startswith('md'):
661 bootable = 0
662 parts = checkbootloader.getRaidDisks(device, 1, stripPart=0)
663 parts.sort()
664 return parts
665
666 return [device]
667
668 def writeGrub(self, instRoot, fsset, bl, langs, kernelList, chainList,
669 defaultDev, justConfigFile):
670 if len(kernelList) < 1:
671 return ""
672
673 images = bl.images.getImages()
674 rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
675
676 if not os.path.isdir(instRoot + '/boot/grub/'):
677 os.mkdir(instRoot + '/boot/grub', 0755)
678
679 # XXX old config file should be read here for upgrade
680
681 cf = '/boot/grub/grub.conf'
682 self.perms = 0600
683 if os.access (instRoot + cf, os.R_OK):
684 self.perms = os.stat(instRoot + cf)[0] & 0777
685 os.rename(instRoot + cf,
686 instRoot + cf + '.rpmsave')
687
688 grubTarget = bl.getDevice()
689 target = "mbr"
690 if grubTarget[-1].isdigit() and not grubTarget.startswith('md'):
691 target = "partition"
692
693 f = open(instRoot + cf, "w+")
694
695 f.write("# grub.conf generated by anaconda\n")
696 f.write("#\n")
697 f.write("# Note that you do not have to rerun grub "
698 "after making changes to this file\n")
699
700 bootDev = fsset.getEntryByMountPoint("/boot")
701 grubPath = "/grub"
702 cfPath = "/"
703 if not bootDev:
704 bootDev = fsset.getEntryByMountPoint("/")
705 grubPath = "/boot/grub"
706 cfPath = "/boot/"
707 f.write("# NOTICE: You do not have a /boot partition. "
708 "This means that\n")
709 f.write("# all kernel and initrd paths are relative "
710 "to /, eg.\n")
711 else:
712 f.write("# NOTICE: You have a /boot partition. This means "
713 "that\n")
714 f.write("# all kernel and initrd paths are relative "
715 "to /boot/, eg.\n")
716
717 bootDevs = self.getPhysicalDevices(bootDev.device.getDevice())
718 bootDev = bootDev.device.getDevice()
719
720 f.write('# root %s\n' % self.grubbyPartitionName(bootDevs[0]))
721 f.write("# kernel %svmlinuz-version ro "
722 "root=/dev/%s\n" % (cfPath, rootDev))
723 f.write("# initrd %sinitrd-version.img\n" % (cfPath))
724 f.write("#boot=/dev/%s\n" % (grubTarget))
725
726 # Check to see if smp kernel should be default or not
727 if isys.smpAvailable() or isys.htavailable():
728 smpCapable=1
729 else:
730 smpCapable=0
731
732 # get the default image to boot... we have to walk and find it
733 # since grub indexes by where it is in the config file
734 if defaultDev == rootDev:
735 for kernel in range(0, len(kernelList)):
736 default=kernel
737 version=kernelList[kernel][2]
738 if version.find('smp')<0 and not smpCapable:
739 break
740 if version.find('smp')>=0 and smpCapable:
741 break
742 else:
743 # if the default isn't linux, it's the first thing in the
744 # chain list
745 default = len(kernelList)
746
747 # keep track of which devices are used for the device.map
748 usedDevs = {}
749
750 f.write('default=%s\n' % (default))
751 if len(chainList) > 0:
752 timeout = 5
753 else:
754 timeout = 5
755 f.write('timeout=%d\n' %(timeout,))
756
757 if self.serial == 1:
758 # grub the 0-based number of the serial console device
759 unit = self.serialDevice[-1]
760
761 # and we want to set the speed too
762 speedend = 0
763 for char in self.serialOptions:
764 if char not in string.digits:
765 break
766 speedend = speedend + 1
767 if speedend != 0:
768 speed = self.serialOptions[:speedend]
769 else:
770 # reasonable default
771 speed = "9600"
772
773 f.write("serial --unit=%s --speed=%s\n" %(unit, speed))
774 f.write("terminal --timeout=5 serial console\n")
775 else:
776 # we only want splashimage if they're not using a serial console
777 if os.access("%s/boot/grub/splash.xpm.gz" %(instRoot,), os.R_OK):
778 f.write('splashimage=%s%sgrub/splash.xpm.gz\n'
779 % (self.grubbyPartitionName(bootDevs[0]), cfPath))
780 f.write("hiddenmenu\n")
781
782 for dev in self.getPhysicalDevices(grubTarget):
783 usedDevs[dev] = 1
784
785 if self.password:
786 f.write('password --md5 %s\n' %(self.password))
787
788 for (label, longlabel, version) in kernelList:
789 kernelTag = "-" + version
790 kernelFile = "%svmlinuz%s" % (cfPath, kernelTag)
791
792 initrd = booty.makeInitrd (kernelTag, instRoot)
793
794 f.write('title %s (%s)\n' % (longlabel, version))
795 f.write('\troot %s\n' % self.grubbyPartitionName(bootDevs[0]))
796
797 realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
798 realroot = " root=%s" %(realroot,)
799
800 f.write('\tkernel %s ro%s' % (kernelFile, realroot))
801 if self.args.get():
802 f.write(' %s' % self.args.get())
803 f.write('\n')
804
805 if os.access (instRoot + initrd, os.R_OK):
806 f.write('\tinitrd %sinitrd%s.img\n' % (cfPath, kernelTag))
807
808 for (label, longlabel, device) in chainList:
809 if ((not longlabel) or (longlabel == "")):
810 continue
811 f.write('title %s\n' % (longlabel))
812 f.write('\trootnoverify %s\n' % self.grubbyPartitionName(device))
813 # f.write('\tmakeactive\n')
814 f.write('\tchainloader +1')
815 f.write('\n')
816 usedDevs[device] = 1
817
818 f.close()
819 os.chmod(instRoot + "/boot/grub/grub.conf", self.perms)
820
821 try:
822 # make symlink for menu.lst (default config file name)
823 if os.access (instRoot + "/boot/grub/menu.lst", os.R_OK):
824 os.rename(instRoot + "/boot/grub/menu.lst",
825 instRoot + "/boot/grub/menu.lst.rpmsave")
826 os.symlink("./grub.conf", instRoot + "/boot/grub/menu.lst")
827 except:
828 pass
829
830 try:
831 # make symlink for /etc/grub.conf (config files belong in /etc)
832 if os.access (instRoot + "/etc/grub.conf", os.R_OK):
833 os.rename(instRoot + "/etc/grub.conf",
834 instRoot + "/etc/grub.conf.rpmsave")
835 os.symlink("../boot/grub/grub.conf", instRoot + "/etc/grub.conf")
836 except:
837 pass
838
839 for dev in self.getPhysicalDevices(rootDev):
840 usedDevs[dev] = 1
841
842 if not os.access(instRoot + "/boot/grub/device.map", os.R_OK):
843 f = open(instRoot + "/boot/grub/device.map", "w+")
844 f.write("# this device map was generated by anaconda\n")
845 f.write("(fd0) /dev/fd0\n")
846 devs = usedDevs.keys()
847 usedDevs = {}
848 for dev in devs:
849 drive = getDiskPart(dev)[0]
850 if usedDevs.has_key(drive):
851 continue
852 usedDevs[drive] = 1
853 devs = usedDevs.keys()
854 devs.sort()
855 for drive in devs:
856 # XXX hack city. If they're not the sort of thing that'll
857 # be in the device map, they shouldn't still be in the list.
858 if not drive.startswith('md'):
859 f.write("(%s) /dev/%s\n" % (self.grubbyDiskName(drive),
860 drive))
861 f.close()
862
863 if self.forceLBA32:
864 forcelba = "--force-lba "
865 else:
866 forcelba = ""
867
868 sysconf = '/etc/sysconfig/grub'
869 if os.access (instRoot + sysconf, os.R_OK):
870 self.perms = os.stat(instRoot + sysconf)[0] & 0777
871 os.rename(instRoot + sysconf,
872 instRoot + sysconf + '.rpmsave')
873 # if it's an absolute symlink, just get it out of our way
874 elif (os.path.islink(instRoot + sysconf) and
875 os.readlink(instRoot + sysconf)[0] == '/'):
876 os.rename(instRoot + sysconf,
877 instRoot + sysconf + '.rpmsave')
878 f = open(instRoot + sysconf, 'w+')
879 f.write("boot=/dev/%s\n" %(grubTarget,))
880 # XXX forcelba never gets read back...
881 if self.forceLBA32:
882 f.write("forcelba=1\n")
883 else:
884 f.write("forcelba=0\n")
885 f.close()
886
887 cmds = []
888 for bootDev in bootDevs:
889 gtPart = self.getMatchingPart(bootDev, grubTarget)
890 gtDisk = self.grubbyPartitionName(getDiskPart(gtPart)[0])
891 bPart = self.grubbyPartitionName(bootDev)
892 cmd = "root %s" % (bPart,)
893 cmds.append(cmd)
894
895 stage1Target = gtDisk
896 if target == "partition":
897 stage1Target = self.grubbyPartitionName(gtPart)
898
899 cmd = "install %s%s/stage1 d %s %s/stage2 p %s%s/grub.conf" % \
900 (forcelba, grubPath, stage1Target, grubPath, bPart, grubPath)
901 cmds.append(cmd)
902
903 if not justConfigFile:
904 log("GRUB commands:")
905 for cmd in cmds:
906 log("\t%s\n", cmd)
907
908 # copy the stage files over into /boot
909 rhpl.executil.execWithRedirect( "/sbin/grub-install",
910 ["/sbin/grub-install", "--just-copy"],
911 stdout = "/dev/tty5", stderr = "/dev/tty5",
912 root = instRoot)
913
914
915
916 # FIXME: hack to try to make sure everything is written to the disk
917 if cfPath == "/":
918 syncDataToDisk(bootDev, "/boot", instRoot)
919 else:
920 syncDataToDisk(bootDev, "/", instRoot)
921
922 # really install the bootloader
923 p = os.pipe()
924 for cmd in cmds:
925 os.write(p[1], cmd + '\n')
926 os.close(p[1])
927 rhpl.executil.execWithRedirect('/sbin/grub' ,
928 [ "grub", "--batch", "--no-floppy",
929 "--device-map=/boot/grub/device.map" ],
930 stdin = p[0],
931 stdout = "/dev/tty5", stderr = "/dev/tty5",
932 root = instRoot)
933 os.close(p[0])
934
935 return ""
936
937 def getMatchingPart(self, bootDev, target):
938 bootName, bootPartNum = getDiskPart(bootDev)
939 devices = self.getPhysicalDevices(target)
940 for device in devices:
941 name, partNum = getDiskPart(device)
942 if name == bootName:
943 return device
944 return devices[0]
945
946 def grubbyDiskName(self, name):
947 return "hd%d" % self.drivelist.index(name)
948
949 def grubbyPartitionName(self, dev):
950 (name, partNum) = getDiskPart(dev)
951 if partNum != None:
952 return "(%s,%d)" % (self.grubbyDiskName(name), partNum)
953 else:
954 return "(%s)" %(self.grubbyDiskName(name))
955
956
957 def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList,
958 chainList, defaultDev):
959 config = bootloaderInfo.getBootloaderConfig(self, instRoot, fsset,
960 bl, langs,
961 kernelList, chainList,
962 defaultDev)
963
964 liloTarget = bl.getDevice()
965
966 config.addEntry("boot", '/dev/' + liloTarget, replace = 0)
967 config.addEntry("map", "/boot/map", replace = 0)
968 config.addEntry("install", "/boot/boot.b", replace = 0)
969 message = "/boot/message"
970
971 if self.pure is not None and not self.useGrubVal:
972 config.addEntry("restricted", replace = 0)
973 config.addEntry("password", self.pure, replace = 0)
974
975
976 import language
977 for lang in language.expandLangs(langs.getDefault()):
978 fn = "/boot/message." + lang
979 if os.access(instRoot + fn, os.R_OK):
980 message = fn
981 break
982
983 if self.serial == 1:
984 # grab the 0-based number of the serial console device
985 unit = self.serialDevice[-1]
986 # FIXME: we should probably put some options, but lilo
987 # only supports up to 9600 baud so just use the defaults
988 # it's better than nothing :(
989 config.addEntry("serial=%s" %(unit,))
990 else:
991 # message screws up serial console
992 if os.access(instRoot + message, os.R_OK):
993 config.addEntry("message", message, replace = 0)
994
995 if not config.testEntry('lba32'):
996 if self.forceLBA32 or (bl.above1024 and
997 butil.getArch() != "x86_64" and
998 edd.detect()):
999 config.addEntry("lba32", replace = 0)
1000
1001 return config
1002
1003 # this is a hackish function that depends on the way anaconda writes
1004 # out the grub.conf with a #boot= comment
1005 # XXX this falls into the category of self.doUpgradeOnly
1006 def upgradeGrub(self, instRoot, fsset, bl, langs, kernelList, chainList,
1007 defaultDev, justConfigFile):
1008 if justConfigFile:
1009 return ""
1010
1011 theDev = None
1012 for (fn, stanza) in [ ("/etc/sysconfig/grub", "boot="),
1013 ("/boot/grub/grub.conf", "#boot=") ]:
1014 try:
1015 f = open(instRoot + fn, "r")
1016 except:
1017 continue
1018
1019 # the following bits of code are straight from checkbootloader.py
1020 lines = f.readlines()
1021 f.close()
1022 for line in lines:
1023 if line.startswith(stanza):
1024 theDev = checkbootloader.getBootDevString(line)
1025 break
1026 if theDev is not None:
1027 break
1028
1029 if theDev is None:
1030 # we could find the dev before, but can't now... cry about it
1031 return ""
1032
1033 # migrate info to /etc/sysconfig/grub
1034 sysconf = '/etc/sysconfig/grub'
1035 if not os.access(instRoot + sysconf, os.R_OK):
1036 f = open(instRoot + sysconf, "w+")
1037 f.write("boot=%s\n" %(theDev,))
1038 # XXX forcelba never gets read back at all...
1039 if self.forceLBA32:
1040 f.write("forcelba=1\n")
1041 else:
1042 f.write("forcelba=0\n")
1043 f.close()
1044
1045 # more suckage. grub-install can't work without a valid /etc/mtab
1046 # so we have to do shenanigans to get updated grub installed...
1047 # steal some more code above
1048 bootDev = fsset.getEntryByMountPoint("/boot")
1049 grubPath = "/grub"
1050 cfPath = "/"
1051 if not bootDev:
1052 bootDev = fsset.getEntryByMountPoint("/")
1053 grubPath = "/boot/grub"
1054 cfPath = "/boot/"
1055
1056 masterBootDev = bootDev.device.getDevice(asBoot = 0)
1057 if masterBootDev[0:2] == 'md':
1058 rootDevs = checkbootloader.getRaidDisks(masterBootDev, raidLevel=1,
1059 stripPart = 0)
1060 else:
1061 rootDevs = [masterBootDev]
1062
1063 if theDev[5:7] == 'md':
1064 stage1Devs = checkbootloader.getRaidDisks(theDev[5:], raidLevel=1)
1065 else:
1066 stage1Devs = [theDev[5:]]
1067
1068 for stage1Dev in stage1Devs:
1069 # cross fingers; if we can't find a root device on the same
1070 # hardware as this boot device, we just blindly hope the first
1071 # thing in the list works.
1072
1073 grubbyStage1Dev = self.grubbyPartitionName(stage1Dev)
1074
1075 grubbyRootPart = self.grubbyPartitionName(rootDevs[0])
1076
1077 for rootDev in rootDevs:
1078 testGrubbyRootDev = getDiskPart(rootDev)[0]
1079 testGrubbyRootDev = self.grubbyPartitionName(testGrubbyRootDev)
1080
1081 if grubbyStage1Dev == testGrubbyRootDev:
1082 grubbyRootPart = self.grubbyPartitionName(rootDev)
1083 break
1084
1085 cmd = "root %s\ninstall %s/stage1 d %s %s/stage2 p %s%s/grub.conf" \
1086 % (grubbyRootPart, grubPath, grubbyStage1Dev,
1087 grubPath, grubbyRootPart, grubPath)
1088
1089 if not justConfigFile:
1090 log("GRUB command %s", cmd)
1091
1092 # copy the stage files over into /boot
1093 rhpl.executil.execWithRedirect( "/sbin/grub-install",
1094 ["/sbin/grub-install", "--just-copy"],
1095 stdout = "/dev/tty5", stderr = "/dev/tty5",
1096 root = instRoot)
1097
1098 # get the stage files synced to disk
1099 import isys
1100 isys.sync()
1101 isys.sync()
1102 isys.sync()
1103
1104 # really install the bootloader
1105 p = os.pipe()
1106 os.write(p[1], cmd + '\n')
1107 os.close(p[1])
1108 rhpl.executil.execWithRedirect('/sbin/grub' ,
1109 [ "grub", "--batch", "--no-floppy",
1110 "--device-map=/boot/grub/device.map" ],
1111 stdin = p[0],
1112 stdout = "/dev/tty5", stderr = "/dev/tty5",
1113 root = instRoot)
1114 os.close(p[0])
1115
1116 return ""
1117
1118
1119 def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1120 defaultDev, justConfig, intf):
1121 # XXX HACK ALERT - see declaration above
1122 if self.doUpgradeOnly:
1123 if self.useGrubVal:
1124 self.upgradeGrub(instRoot, fsset, bl, langs, kernelList,
1125 chainList, defaultDev, justConfig)
1126
1127 # and the hacks continue. with 2.6, ide-scsi isn't used
1128 # anymore (#116622)
1129 import isys
1130 cdrw = isys.ideCdRwList()
1131 torem = []
1132 for device in cdrw:
1133 torem.append("%s=ide-scsi" %(device,))
1134
1135 for fn in ("/etc/lilo.conf", "/boot/grub/grub.conf",
1136 "/etc/lilo.conf.anaconda"):
1137 if not os.path.exists(instRoot + fn):
1138 continue
1139 f = open(instRoot + fn, "r")
1140 buf = f.read()
1141 f.close()
1142 for dev in torem:
1143 buf = buf.replace(dev, "")
1144 f = open(instRoot + fn, "w")
1145 f.write(buf)
1146 f.close()
1147 return
1148 if len(kernelList) < 1:
1149 self.noKernelsWarn(intf)
1150
1151 str = self.writeGrub(instRoot, fsset, bl, langs, kernelList,
1152 chainList, defaultDev,
1153 justConfig | (not self.useGrubVal))
1154 # XXX move the lilo.conf out of the way if they're using GRUB
1155 # so that /sbin/installkernel does a more correct thing
1156 if self.useGrubVal and os.access(instRoot + '/etc/lilo.conf', os.R_OK):
1157 os.rename(instRoot + "/etc/lilo.conf",
1158 instRoot + "/etc/lilo.conf.anaconda")
1159
1160
1161
1162 def getArgList(self):
1163 args = bootloaderInfo.getArgList(self)
1164
1165 if self.forceLBA32:
1166 args.append("--lba32")
1167 if self.password:
1168 args.append("--md5pass=%s" %(self.password))
1169
1170
1171 # XXX add location of bootloader here too
1172
1173 return args
1174
1175 def __init__(self):
1176 bootloaderInfo.__init__(self)
1177 # XXX use checkbootloader to determine what to default to
1178 self.useGrubVal = 1
1179 self.kernelLocation = "/boot/"
1180 self.configfile = "/etc/lilo.conf"
1181 self.password = None
1182 self.pure = None
1183
1184 class s390BootloaderInfo(bootloaderInfo):
1185 def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList,
1186 chainList, defaultDev):
1187 images = bl.images.getImages()
1188
1189 # on upgrade read in the lilo config file
1190 lilo = LiloConfigFile ()
1191 self.perms = 0600
1192 if os.access (instRoot + self.configfile, os.R_OK):
1193 self.perms = os.stat(instRoot + self.configfile)[0] & 0777
1194 lilo.read (instRoot + self.configfile)
1195 os.rename(instRoot + self.configfile,
1196 instRoot + self.configfile + '.rpmsave')
1197
1198 # Remove any invalid entries that are in the file; we probably
1199 # just removed those kernels.
1200 for label in lilo.listImages():
1201 (fsType, sl, path, other) = lilo.getImage(label)
1202 if fsType == "other": continue
1203
1204 if not os.access(instRoot + sl.getPath(), os.R_OK):
1205 lilo.delImage(label)
1206
1207 rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1208 if not rootDev:
1209 raise RuntimeError, "Installing zipl, but there is no root device"
1210
1211 if rootDev == defaultDev:
1212 lilo.addEntry("default", kernelList[0][0])
1213 else:
1214 lilo.addEntry("default", chainList[0][0])
1215
1216 for (label, longlabel, version) in kernelList:
1217 kernelTag = "-" + version
1218 kernelFile = self.kernelLocation + "vmlinuz" + kernelTag
1219
1220 try:
1221 lilo.delImage(label)
1222 except IndexError, msg:
1223 pass
1224
1225 sl = LiloConfigFile(imageType = "image", path = kernelFile)
1226
1227 initrd = booty.makeInitrd (kernelTag, instRoot)
1228
1229 sl.addEntry("label", label)
1230 if os.access (instRoot + initrd, os.R_OK):
1231 sl.addEntry("initrd",
1232 "%sinitrd%s.img" %(self.kernelLocation, kernelTag))
1233
1234 sl.addEntry("read-only")
1235 sl.addEntry("root", '/dev/' + rootDev)
1236 sl.addEntry("ipldevice", '/dev/' + rootDev[:-1])
1237
1238 if self.args.get():
1239 sl.addEntry('append', '"%s"' % self.args.get())
1240
1241 lilo.addImage (sl)
1242
1243 for (label, longlabel, device) in chainList:
1244 if ((not label) or (label == "")):
1245 continue
1246 try:
1247 (fsType, sl, path, other) = lilo.getImage(label)
1248 lilo.delImage(label)
1249 except IndexError:
1250 sl = LiloConfigFile(imageType = "other",
1251 path = "/dev/%s" %(device))
1252 sl.addEntry("optional")
1253
1254 sl.addEntry("label", label)
1255 lilo.addImage (sl)
1256
1257 # Sanity check #1. There could be aliases in sections which conflict
1258 # with the new images we just created. If so, erase those aliases
1259 imageNames = {}
1260 for label in lilo.listImages():
1261 imageNames[label] = 1
1262
1263 for label in lilo.listImages():
1264 (fsType, sl, path, other) = lilo.getImage(label)
1265 if sl.testEntry('alias'):
1266 alias = sl.getEntry('alias')
1267 if imageNames.has_key(alias):
1268 sl.delEntry('alias')
1269 imageNames[alias] = 1
1270
1271 # Sanity check #2. If single-key is turned on, go through all of
1272 # the image names (including aliases) (we just built the list) and
1273 # see if single-key will still work.
1274 if lilo.testEntry('single-key'):
1275 singleKeys = {}
1276 turnOff = 0
1277 for label in imageNames.keys():
1278 l = label[0]
1279 if singleKeys.has_key(l):
1280 turnOff = 1
1281 singleKeys[l] = 1
1282 if turnOff:
1283 lilo.delEntry('single-key')
1284
1285 return lilo
1286
1287 def writeChandevConf(self, bl, instroot): # S/390 only
1288 cf = "/etc/chandev.conf"
1289 self.perms = 0644
1290 if bl.args.chandevget():
1291 fd = os.open(instroot + "/etc/chandev.conf",
1292 os.O_WRONLY | os.O_CREAT)
1293 os.write(fd, "noauto\n")
1294 for cdev in bl.args.chandevget():
1295 os.write(fd,'%s\n' % cdev)
1296 os.close(fd)
1297 return ""
1298
1299
1300 def writeZipl(self, instRoot, fsset, bl, langs, kernelList, chainList,
1301 defaultDev, justConfigFile):
1302 images = bl.images.getImages()
1303 rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1304
1305 cf = '/etc/zipl.conf'
1306 self.perms = 0600
1307 if os.access (instRoot + cf, os.R_OK):
1308 self.perms = os.stat(instRoot + cf)[0] & 0777
1309 os.rename(instRoot + cf,
1310 instRoot + cf + '.rpmsave')
1311
1312 f = open(instRoot + cf, "w+")
1313
1314 f.write('[defaultboot]\n')
1315 f.write('default=' + kernelList[0][0] + '\n')
1316 f.write('target=%s\n' % (self.kernelLocation))
1317
1318 cfPath = "/boot/"
1319 for (label, longlabel, version) in kernelList:
1320 kernelTag = "-" + version
1321 kernelFile = "%svmlinuz%s" % (cfPath, kernelTag)
1322
1323 initrd = booty.makeInitrd (kernelTag, instRoot)
1324 f.write('[%s]\n' % (label))
1325 f.write('\timage=%s\n' % (kernelFile))
1326 if os.access (instRoot + initrd, os.R_OK):
1327 f.write('\tramdisk=%sinitrd%s.img\n' %(self.kernelLocation,
1328 kernelTag))
1329 realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
1330 f.write('\tparameters="root=%s' %(realroot,))
1331 if bl.args.get():
1332 f.write(' %s' % (bl.args.get()))
1333 f.write('"\n')
1334
1335 f.close()
1336
1337 if not justConfigFile:
1338 argv = [ "/sbin/zipl" ]
1339 rhpl.executil.execWithRedirect(argv[0], argv, root = instRoot,
1340 stdout = "/dev/stdout",
1341 stderr = "/dev/stderr")
1342
1343 return ""
1344
1345 def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1346 defaultDev, justConfig, intf):
1347 str = self.writeZipl(instRoot, fsset, bl, langs, kernelList,
1348 chainList, defaultDev,
1349 justConfig | (not self.useZiplVal))
1350 str = self.writeChandevConf(bl, instRoot)
1351
1352 def __init__(self):
1353 bootloaderInfo.__init__(self)
1354 self.useZiplVal = 1 # only used on s390
1355 self.kernelLocation = "/boot/"
1356 self.configfile = "/etc/zipl.conf"
1357
1358
1359 class alphaBootloaderInfo(bootloaderInfo):
1360 def wholeDevice (self, path):
1361 (device, foo) = getDiskPart(path)
1362 return device
1363
1364 def partitionNum (self, path):
1365 # getDiskPart returns part numbers 0-based; we need it one based
1366 # *sigh*
1367 (foo, partitionNumber) = getDiskPart(path)
1368 return partitionNumber + 1
1369
1370 # See if we would have to use MILO. MILO isn't supported by Red Hat.
1371 def useMilo (self):
1372 try:
1373 f = open ('/proc/cpuinfo', 'ro')
1374 except:
1375 return
1376 lines = f.readlines ()
1377 f.close()
1378 serial = ""
1379 for line in lines:
1380 if line.find("system serial number") != -1:
1381 serial = string.strip (string.split (line, ':')[1])
1382 break
1383
1384 if serial and len (serial) >= 4 and serial.startswith("MILO"):
1385 return 1
1386 else:
1387 return 0
1388
1389 def writeAboot(self, instRoot, fsset, bl, langs, kernelList,
1390 chainList, defaultDev, justConfig):
1391 # Get bootDevice and rootDevice
1392 rootDevice = fsset.getEntryByMountPoint("/").device.getDevice()
1393 if fsset.getEntryByMountPoint("/boot"):
1394 bootDevice = fsset.getEntryByMountPoint("/boot").device.getDevice()
1395 else:
1396 bootDevice = rootDevice
1397 bootnotroot = bootDevice != rootDevice
1398
1399 # If /etc/aboot.conf already exists we rename it
1400 # /etc/aboot.conf.rpmsave.
1401 if os.path.isfile(instRoot + self.configfile):
1402 os.rename (instRoot + self.configfile,
1403 instRoot + self.configfile + ".rpmsave")
1404
1405 # Then we create the necessary files. If the root device isn't
1406 # the boot device, we create /boot/etc/ where the aboot.conf
1407 # will live, and we create /etc/aboot.conf as a symlink to it.
1408 if bootnotroot:
1409 # Do we have /boot/etc ? If not, create one
1410 if not os.path.isdir (instRoot + '/boot/etc'):
1411 os.mkdir(instRoot + '/boot/etc', 0755)
1412
1413 # We install the symlink (/etc/aboot.conf has already been
1414 # renamed in necessary.)
1415 os.symlink("../boot" + self.configfile, instRoot + self.configfile)
1416
1417 cfPath = instRoot + "/boot" + self.configfile
1418 # Kernel path is set to / because a boot partition will
1419 # be a root on its own.
1420 kernelPath = '/'
1421 # Otherwise, we just need to create /etc/aboot.conf.
1422 else:
1423 cfPath = instRoot + self.configfile
1424 kernelPath = self.kernelLocation
1425
1426 # If we already have an aboot.conf, rename it
1427 if os.access (cfPath, os.R_OK):
1428 self.perms = os.stat(cfPath)[0] & 0777
1429 os.rename(cfPath, cfPath + '.rpmsave')
1430
1431 # Now we're going to create and populate cfPath.
1432 f = open (cfPath, 'w+')
1433 f.write ("# aboot default configurations\n")
1434
1435 if bootnotroot:
1436 f.write ("# NOTICE: You have a /boot partition. This means that\n")
1437 f.write ("# all kernel paths are relative to /boot/\n")
1438
1439 # bpn is the boot partition number.
1440 bpn = self.partitionNum(bootDevice)
1441 lines = 0
1442
1443 # We write entries line using the following format:
1444 # <line><bpn><kernel-name> root=<rootdev> [options]
1445 # We get all the kernels we need to know about in kernelList.
1446
1447 for (kernel, tag, kernelTag) in kernelList:
1448 kernelFile = "%svmlinuz-%s" %(kernelPath, kernelTag)
1449
1450 f.write("%d:%d%s" %(lines, bpn, kernelFile))
1451
1452 # See if we can come up with an initrd argument that exists
1453 initrd = booty.makeInitrd (kernelTag, instRoot)
1454 if os.access(instRoot + initrd, os.R_OK):
1455 f.write(" initrd=%sinitrd-%s.img" %(kernelPath, kernelTag))
1456
1457 realroot = getRootDevName(initrd, fsset, rootDevice, instRoot)
1458 f.write(" root=%s" %(realroot,))
1459
1460 args = self.args.get()
1461 if args:
1462 f.write(" %s" %(args,))
1463
1464 f.write("\n")
1465 lines = lines + 1
1466
1467 # We're done writing the file
1468 f.close ()
1469 del f
1470
1471 if not justConfig:
1472 # Now we're ready to write the relevant boot information. wbd
1473 # is the whole boot device, bdpn is the boot device partition
1474 # number.
1475 wbd = self.wholeDevice (bootDevice)
1476 bdpn = self.partitionNum (bootDevice)
1477
1478 # Calling swriteboot. The first argument is the disk to write
1479 # to and the second argument is a path to the bootstrap loader
1480 # file.
1481 args = ("swriteboot", ("/dev/%s" % wbd), "/boot/bootlx")
1482 log("swriteboot command: %s" %(args,))
1483 rhpl.executil.execWithRedirect ('/sbin/swriteboot', args,
1484 root = instRoot,
1485 stdout = "/dev/tty5",
1486 stderr = "/dev/tty5")
1487
1488 # Calling abootconf to configure the installed aboot. The
1489 # first argument is the disk to use, the second argument is
1490 # the number of the partition on which aboot.conf resides.
1491 # It's always the boot partition whether it's / or /boot (with
1492 # the mount point being omitted.)
1493 args = ("abootconf", ("/dev/%s" % wbd), str (bdpn))
1494 log("abootconf command: %s" %(args,))
1495 rhpl.executil.execWithRedirect ('/sbin/abootconf', args,
1496 root = instRoot,
1497 stdout = "/dev/tty5",
1498 stderr = "/dev/tty5")
1499
1500
1501 def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1502 defaultDev, justConfig, intf):
1503 if len(kernelList) < 1:
1504 self.noKernelsWarn(intf)
1505
1506 if self.useMilo():
1507 intf.messageWindow(_("MILO Not Supported"),
1508 "This system requires the support of MILO to " +
1509 "boot linux (MILO is not included in this " +
1510 "distribution.) The installation of the " +
1511 "bootloader can't be completed on this system.")
1512 # elif not justConfig FIXME.
1513 else:
1514 self.writeAboot(instRoot, fsset, bl, langs, kernelList,
1515 chainList, defaultDev, justConfig)
1516
1517 def __init__(self):
1518 bootloaderInfo.__init__(self)
1519 self.useGrubVal = 0
1520 self.configfile = "/etc/aboot.conf"
1521 # self.kernelLocation is already set to what we need.
1522 self.password = None
1523 self.pure = None
1524
1525
1526 class ppcBootloaderInfo(bootloaderInfo):
1527 def writeYaboot(self, instRoot, fsset, bl, langs, kernelList,
1528 chainList, defaultDev, justConfigFile):
1529
1530 from flags import flags
1531
1532 yabootTarget = '/dev/%s' %(bl.getDevice())
1533
1534 bootDev = fsset.getEntryByMountPoint("/boot")
1535 if bootDev:
1536 cf = "/boot/etc/yaboot.conf"
1537 cfPath = ""
1538 if not os.path.isdir(instRoot + "/boot/etc"):
1539 os.mkdir(instRoot + "/boot/etc")
1540 else:
1541 bootDev = fsset.getEntryByMountPoint("/")
1542 cfPath = "/boot"
1543 cf = "/etc/yaboot.conf"
1544 bootDev = bootDev.device.getDevice(asBoot = 1)
1545
1546 f = open(instRoot + cf, "w+")
1547
1548 f.write("# yaboot.conf generated by anaconda\n\n")
1549
1550 f.write("boot=%s\n" %(yabootTarget,))
1551 f.write("init-message=Welcome to %s\\!\nHit <TAB> for boot options\n\n"
1552 %(butil.getProductName(),))
1553
1554 (name, partNum) = getDiskPart(bootDev)
1555 partno = partNum + 1 # 1 based
1556 f.write("partition=%s\n" %(partno,))
1557
1558 f.write("timeout=80\n")
1559 f.write("install=/usr/lib/yaboot/yaboot\n")
1560 f.write("delay=5\n")
1561 f.write("enablecdboot\n")
1562 f.write("enableofboot\n")
1563 f.write("enablenetboot\n")
1564
1565 if butil.getPPCMachine() == "PMac":
1566 # write out the first hfs/hfs+ partition as being macosx
1567 for (label, longlabel, device) in chainList:
1568 if ((not label) or (label == "")):
1569 continue
1570 f.write("macosx=/dev/%s\n" %(device,))
1571 break
1572
1573 f.write("magicboot=/usr/lib/yaboot/ofboot\n")
1574
1575 if butil.getPPCMachine() == "pSeries":
1576 f.write("nonvram\n")
1577
1578 if self.password:
1579 f.write("password=%s\n" %(self.password,))
1580 f.write("restricted\n")
1581
1582 f.write("\n")
1583
1584 rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1585
1586 for (label, longlabel, version) in kernelList:
1587 kernelTag = "-" + version
1588 kernelFile = "%s/vmlinuz%s" %(cfPath, kernelTag)
1589
1590 f.write("image=%s\n" %(kernelFile,))
1591 f.write("\tlabel=%s\n" %(label,))
1592 f.write("\tread-only\n")
1593
1594 initrd = booty.makeInitrd(kernelTag, instRoot)
1595 if os.access(instRoot + initrd, os.R_OK):
1596 f.write("\tinitrd=%s/initrd%s.img\n" %(cfPath,kernelTag))
1597
1598 append = "%s" %(self.args.get(),)
1599
1600 realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
1601 if not realroot.startswith("LABEL="):
1602 f.write("\troot=%s\n" %(realroot,))
1603 else:
1604 if len(append) > 0:
1605 append = "%s root=%s" %(append,realroot)
1606 else:
1607 append = "root=%s" %(realroot,)
1608
1609 if len(append) > 0:
1610 f.write("\tappend=\"%s\"\n" %(append,))
1611 f.write("\n")
1612
1613 f.close()
1614 os.chmod(instRoot + cf, 0600)
1615
1616 # FIXME: hack to make sure things are written to disk
1617 import isys
1618 isys.sync()
1619 isys.sync()
1620 isys.sync()
1621
1622 ybinargs = [ "/sbin/mkofboot", "-f", "-C", cf ]
1623 if butil.getPPCMachine() == "pSeries":
1624 ybinargs.extend(["--filesystem", "raw"])
1625
1626
1627 log("running: %s" %(ybinargs,))
1628 if not flags.test:
1629 rhpl.executil.execWithRedirect(ybinargs[0],
1630 ybinargs,
1631 stdout = "/dev/tty5",
1632 stderr = "/dev/tty5",
1633 root = instRoot)
1634
1635 if (not os.access(instRoot + "/etc/yaboot.conf", os.R_OK) and
1636 os.access(instRoot + "/boot/etc/yaboot.conf", os.R_OK)):
1637 os.symlink("../boot/etc/yaboot.conf",
1638 instRoot + "/etc/yaboot.conf")
1639
1640 return ""
1641
1642 def setPassword(self, val, isCrypted = 1):
1643 # yaboot just handles the password and doesn't care if its crypted
1644 # or not
1645 self.password = val
1646
1647 def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1648 defaultDev, justConfig, intf):
1649 if len(kernelList) >= 1:
1650 str = self.writeYaboot(instRoot, fsset, bl, langs, kernelList,
1651 chainList, defaultDev, justConfig)
1652 else:
1653 self.noKernelsWarn(intf)
1654
1655 def __init__(self):
1656 bootloaderInfo.__init__(self)
1657 self.useYabootVal = 1
1658 self.kernelLocation = "/boot"
1659 self.configfile = "/etc/yaboot.conf"
1660
1661
1662 class iseriesBootloaderInfo(bootloaderInfo):
1663 def ddFile(self, inf, of, bs = 4096):
1664 src = os.open(inf, os.O_RDONLY)
1665 dest = os.open(of, os.O_WRONLY | os.O_CREAT)
1666 size = 0
1667
1668 buf = os.read(src, bs)
1669 while len(buf) > 0:
1670 size = size + len(buf)
1671 os.write(dest, buf)
1672 buf = os.read(src, bs)
1673
1674 os.close(src)
1675 os.close(dest)
1676
1677 return size
1678
1679 def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1680 defaultDev, justConfig, intf):
1681 if len(kernelList) < 1:
1682 self.noKernelsWarn(intf)
1683 return
1684 if len(kernelList) > 1:
1685 # FIXME: how can this happen?
1686 log("more than one kernel on iSeries. bailing and just using "
1687 "the first")
1688
1689 # iseries is Weird (tm) -- here's the basic theory
1690 # a) have /boot/vmlinitrd-$(version)
1691 # b) copy default kernel to PReP partition
1692 # c) dd default kernel to /proc/iSeries/mf/C/vmlinux
1693 # d) set cmdline in /boot/cmdline-$(version)
1694 # e) copy cmdline to /proc/iSeries/mf/C/cmdline
1695 # f) set default side to 'C' i /proc/iSeries/mf/side
1696 # g) put default kernel and cmdline on side B too (#91038)
1697
1698 rootDevice = fsset.getEntryByMountPoint("/").device.getDevice()
1699
1700 # write our command line files
1701 for (kernel, tag, kernelTag) in kernelList:
1702 cmdFile = "%scmdline-%s" %(self.kernelLocation, kernelTag)
1703 initrd = "%sinitrd-%s.img" %(self.kernelLocation, kernelTag)
1704 realroot = getRootDevName(initrd, fsset, rootDevice, instRoot)
1705 f = open(instRoot + cmdFile, "w")
1706 f.write("ro root=%s" %(realroot,))
1707 if bl.args.get():
1708 f.write(" %s" %(bl.args.get(),))
1709 f.write("\n")
1710 f.close()
1711 os.chmod(instRoot + cmdFile, 0644)
1712
1713 kernel, tag, kernelTag = kernelList[0]
1714 kernelFile = "%svmlinitrd-%s" %(self.kernelLocation, kernelTag)
1715
1716 # write the kernel to the PReP partition since that's what
1717 # OS/400 will load as NWSSTG
1718 bootDev = bl.getDevice()
1719 if bootDev:
1720 log("Writing kernel %s to PReP partition %s" %(kernelFile,
1721 bootDev))
1722 try:
1723 self.ddFile(instRoot + kernelFile, "%s/dev/%s" %(instRoot,
1724 bootDev))
1725 except Exception, e:
1726 # FIXME: should this be more fatal
1727 log("Failed to write kernel: %s" %(e,))
1728 else:
1729 log("No PReP boot partition, not writing kernel for NWSSTG")
1730
1731
1732 # now, it's a lot faster to boot if we don't make people go back
1733 # into OS/400, so set up side C (used by default for NWSSTG) with
1734 # our current bits
1735 for side in ("C", "B"):
1736 log("Writing kernel and cmdline to side %s" %(side,))
1737 wrotekernel = 0
1738 try:
1739 self.ddFile(instRoot + kernelFile,
1740 "%s/proc/iSeries/mf/%s/vmlinux" %(instRoot, side))
1741 wrotekernel = 1
1742 except Exception, e:
1743 # FIXME: should this be more fatal?
1744 log("Failed to write kernel to side %s: %s" %(side, e))
1745
1746 if wrotekernel == 1:
1747 try:
1748 # blank it. ugh.
1749 f = open("%s/proc/iSeries/mf/%s/cmdline" %(instRoot, side),
1750 "w+")
1751 f.write(" " * 255)
1752 f.close()
1753
1754 self.ddFile("%s/%scmdline-%s" %(instRoot,
1755 self.kernelLocation,
1756 kernelTag),
1757 "%s/proc/iSeries/mf/%s/cmdline" %(instRoot,
1758 side))
1759 except Exception, e:
1760 log("Failed to write kernel command line to side %s: %s"
1761 %(side, e))
1762
1763 log("Setting default side to C")
1764 f = open(instRoot + "/proc/iSeries/mf/side", "w")
1765 f.write("C")
1766 f.close()
1767
1768 def __init__(self):
1769 bootloaderInfo.__init__(self)
1770 self.kernelLocation = "/boot/"
1771
1772 class sparcBootloaderInfo(bootloaderInfo):
1773 def writeSilo(self, instRoot, fsset, bl, langs, kernelList,
1774 chainList, defaultDev, justConfigFile):
1775
1776 from flags import flags
1777
1778 bootDev = fsset.getEntryByMountPoint("/boot")
1779 if bootDev:
1780 cf = "/boot/silo.conf"
1781 mf = "/boot/silo.message"
1782 cfPath = ""
1783 if not os.path.isdir(instRoot + "/boot"):
1784 os.mkdir(instRoot + "/boot")
1785 else:
1786 bootDev = fsset.getEntryByMountPoint("/")
1787 cf = "/etc/silo.conf"
1788 mf = "/etc/silo.message"
1789 cfPath = "/boot"
1790 bootDev = bootDev.device.getDevice(asBoot = 1)
1791
1792 f = open(instRoot + mf, "w+")
1793 f.write("Welcome to %s!\nHit <TAB> for boot options\n\n" % \
1794 (butil.getProductName(),))
1795 f.close()
1796 os.chmod(instRoot + mf, 0600)
1797
1798 f = open(instRoot + cf, "w+")
1799 f.write("# silo.conf generated by anaconda\n\n")
1800
1801 f.write("#boot=%s\n" % (bootDev,))
1802 f.write("message=%s\n" % (mf,))
1803 f.write("timeout=50\n")
1804
1805 (name, partNum) = getDiskPart(bootDev)
1806 partno = partNum + 1
1807 f.write("partition=%s\n" % (partno,))
1808
1809 if self.password:
1810 f.write("password=%s\n" % (self.password,))
1811 f.write("restricted\n")
1812
1813 f.write("default=%s\n" % (kernelList[0][0],))
1814 f.write("\n")
1815
1816 rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1817
1818 for (label, longlabel, version) in kernelList:
1819 kernelTag = "-" + version
1820 kernelFile = "%s/vmlinuz%s" % (cfPath, kernelTag)
1821
1822 f.write("image=%s\n" % (kernelFile,))
1823 f.write("\tlabel=%s\n" % (label,))
1824 f.write("\tread-only\n")
1825
1826 initrd = booty.makeInitrd(kernelTag, instRoot)
1827 if os.access(instRoot + initrd, os.R_OK):
1828 f.write("\tinitrd=%s/initrd%s.img\n" % (cfPath, kernelTag))
1829
1830 append = "%s" % (self.args.get(),)
1831
1832 realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
1833 if not realroot.startswith("LABEL="):
1834 f.write("\troot=%s\n" % (realroot,))
1835 else:
1836 if len(append) > 0:
1837 append = "%s root=%s" % (append, realroot)
1838 else:
1839 append = "root=%s" % (realroot,)
1840
1841 if len(append) > 0:
1842 f.write("\tappend=\"%s\"\n" % (append,))
1843 f.write("\n")
1844
1845 f.close()
1846 os.chmod(instRoot + cf, 0600)
1847
1848 # FIXME: hack to make sure things are written to disk
1849 import isys
1850 isys.sync()
1851 isys.sync()
1852 isys.sync()
1853
1854 backup = "%s/backup.b" % (cfPath,)
1855 sbinargs = ["/sbin/silo", "-f", "-C", cf, "-S", backup]
1856 if butil.getSparcMachine() == "sun4u":
1857 sbinargs += ["-u"]
1858 else:
1859 sbinargs += ["-U"]
1860
1861 log("running: %s" % (sbinargs,))
1862 if not flags.test:
1863 rhpl.executil.execWithRedirect(sbinargs[0],
1864 sbinargs,
1865 stdout = "/dev/tty5",
1866 stderr = "/dev/tty5",
1867 root = instRoot)
1868
1869 if (not os.access(instRoot + "/etc/silo.conf", os.R_OK) and
1870 os.access(instRoot + "/boot/etc/silo.conf", os.R_OK)):
1871 os.symlink("../boot/etc/silo.conf",
1872 instRoot + "/etc/silo.conf")
1873
1874 return ""
1875
1876 def setPassword(self, val, isCrypted = 1):
1877 # silo just handles the password unencrypted
1878 self.password = val
1879
1880 def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1881 defaultDev, justConfig, intf):
1882 if len(kernelList) >= 1:
1883 self.writeSilo(instRoot, fsset, bl, langs, kernelList, chainList,
1884 defaultDev, justConfig)
1885 else:
1886 self.noKernelsWarn(intf)
1887
1888 def __init__(self):
1889 bootloaderInfo.__init__(self)
1890 self.useSiloVal = 1
1891 self.kernelLocation = "/boot"
1892 self.configfile = "/etc/silo.conf"
1893
1894 ###############
1895 # end of boot loader objects... these are just some utility functions used
1896
1897 # return (disk, partition number) eg ('hda', 1)
1898 def getDiskPart(dev):
1899 cut = len(dev)
1900 if (dev.startswith('rd/') or dev.startswith('ida/') or
1901 dev.startswith('cciss/')):
1902 if dev[-2] == 'p':
1903 cut = -1
1904 elif dev[-3] == 'p':
1905 cut = -2
1906 else:
1907 if dev[-2] in string.digits:
1908 cut = -2
1909 elif dev[-1] in string.digits:
1910 cut = -1
1911
1912 name = dev[:cut]
1913
1914 # hack off the trailing 'p' from /dev/cciss/*, for example
1915 if name[-1] == 'p':
1916 for letter in name:
1917 if letter not in string.letters and letter != "/":
1918 name = name[:-1]
1919 break
1920
1921 if cut < 0:
1922 partNum = int(dev[cut:]) - 1
1923 else:
1924 partNum = None
1925
1926 return (name, partNum)
1927
1928 # hackery to determine if we should do root=LABEL=/ or whatnot
1929 # as usual, knows too much about anaconda
1930 def getRootDevName(initrd, fsset, rootDev, instRoot):
1931 if not os.access(instRoot + initrd, os.R_OK):
1932 return "/dev/%s" % (rootDev,)
1933
1934 try:
1935 rootEntry = fsset.getEntryByMountPoint("/")
1936 if rootEntry.getLabel() is not None:
1937 return "LABEL=%s" %(rootEntry.getLabel(),)
1938 return "/dev/%s" %(rootDev,)
1939 except:
1940 return "/dev/%s" %(rootDev,)
1941

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed