/[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.2 - (show annotations) (download) (as text)
Wed Jul 13 21:59:02 2005 UTC (19 years, 5 months ago) by slords
Branch: MAIN
Changes since 1.1: +5 -1 lines
Content type: text/x-python
Pick correct kernel based on hyperthreading and smp capabilities

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

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