/[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.3 - (show annotations) (download) (as text)
Wed Jul 13 22:11:53 2005 UTC (19 years, 5 months ago) by slords
Branch: MAIN
Changes since 1.2: +11 -2 lines
Content type: text/x-python
Update to kernel selection

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 # Check to see if smp kernel should be default or not
725 if isys.smpAvailable() or isys.htavailable():
726 smpCapable=1
727 else:
728 smpCapable=0
729
730 # get the default image to boot... we have to walk and find it
731 # since grub indexes by where it is in the config file
732 if defaultDev == rootDev:
733 for kernel in range(0, len(kernelList)):
734 default=kernel
735 version=kernelList[kernel][2]
736 if version.find('smp')<0 and not smpCapable:
737 break
738 if version.find('smp')>=0 and smpCapable:
739 break
740 else:
741 # if the default isn't linux, it's the first thing in the
742 # chain list
743 default = len(kernelList)
744
745 # keep track of which devices are used for the device.map
746 usedDevs = {}
747
748 f.write('default=%s\n' % (default))
749 if len(chainList) > 0:
750 timeout = 5
751 else:
752 timeout = 5
753 f.write('timeout=%d\n' %(timeout,))
754
755 if self.serial == 1:
756 # grub the 0-based number of the serial console device
757 unit = self.serialDevice[-1]
758
759 # and we want to set the speed too
760 speedend = 0
761 for char in self.serialOptions:
762 if char not in string.digits:
763 break
764 speedend = speedend + 1
765 if speedend != 0:
766 speed = self.serialOptions[:speedend]
767 else:
768 # reasonable default
769 speed = "9600"
770
771 f.write("serial --unit=%s --speed=%s\n" %(unit, speed))
772 f.write("terminal --timeout=5 serial console\n")
773 else:
774 # we only want splashimage if they're not using a serial console
775 if os.access("%s/boot/grub/splash.xpm.gz" %(instRoot,), os.R_OK):
776 f.write('splashimage=%s%sgrub/splash.xpm.gz\n'
777 % (self.grubbyPartitionName(bootDevs[0]), cfPath))
778 f.write("hiddenmenu\n")
779
780 for dev in self.getPhysicalDevices(grubTarget):
781 usedDevs[dev] = 1
782
783 if self.password:
784 f.write('password --md5 %s\n' %(self.password))
785
786 for (label, longlabel, version) in kernelList:
787 kernelTag = "-" + version
788 kernelFile = "%svmlinuz%s" % (cfPath, kernelTag)
789
790 initrd = booty.makeInitrd (kernelTag, instRoot)
791
792 f.write('title %s (%s)\n' % (longlabel, version))
793 f.write('\troot %s\n' % self.grubbyPartitionName(bootDevs[0]))
794
795 realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
796 realroot = " root=%s" %(realroot,)
797
798 f.write('\tkernel %s ro%s' % (kernelFile, realroot))
799 if self.args.get():
800 f.write(' %s' % self.args.get())
801 f.write('\n')
802
803 if os.access (instRoot + initrd, os.R_OK):
804 f.write('\tinitrd %sinitrd%s.img\n' % (cfPath, kernelTag))
805
806 for (label, longlabel, device) in chainList:
807 if ((not longlabel) or (longlabel == "")):
808 continue
809 f.write('title %s\n' % (longlabel))
810 f.write('\trootnoverify %s\n' % self.grubbyPartitionName(device))
811 # f.write('\tmakeactive\n')
812 f.write('\tchainloader +1')
813 f.write('\n')
814 usedDevs[device] = 1
815
816 f.close()
817 os.chmod(instRoot + "/boot/grub/grub.conf", self.perms)
818
819 try:
820 # make symlink for menu.lst (default config file name)
821 if os.access (instRoot + "/boot/grub/menu.lst", os.R_OK):
822 os.rename(instRoot + "/boot/grub/menu.lst",
823 instRoot + "/boot/grub/menu.lst.rpmsave")
824 os.symlink("./grub.conf", instRoot + "/boot/grub/menu.lst")
825 except:
826 pass
827
828 try:
829 # make symlink for /etc/grub.conf (config files belong in /etc)
830 if os.access (instRoot + "/etc/grub.conf", os.R_OK):
831 os.rename(instRoot + "/etc/grub.conf",
832 instRoot + "/etc/grub.conf.rpmsave")
833 os.symlink("../boot/grub/grub.conf", instRoot + "/etc/grub.conf")
834 except:
835 pass
836
837 for dev in self.getPhysicalDevices(rootDev):
838 usedDevs[dev] = 1
839
840 if not os.access(instRoot + "/boot/grub/device.map", os.R_OK):
841 f = open(instRoot + "/boot/grub/device.map", "w+")
842 f.write("# this device map was generated by anaconda\n")
843 f.write("(fd0) /dev/fd0\n")
844 devs = usedDevs.keys()
845 usedDevs = {}
846 for dev in devs:
847 drive = getDiskPart(dev)[0]
848 if usedDevs.has_key(drive):
849 continue
850 usedDevs[drive] = 1
851 devs = usedDevs.keys()
852 devs.sort()
853 for drive in devs:
854 # XXX hack city. If they're not the sort of thing that'll
855 # be in the device map, they shouldn't still be in the list.
856 if not drive.startswith('md'):
857 f.write("(%s) /dev/%s\n" % (self.grubbyDiskName(drive),
858 drive))
859 f.close()
860
861 if self.forceLBA32:
862 forcelba = "--force-lba "
863 else:
864 forcelba = ""
865
866 sysconf = '/etc/sysconfig/grub'
867 if os.access (instRoot + sysconf, os.R_OK):
868 self.perms = os.stat(instRoot + sysconf)[0] & 0777
869 os.rename(instRoot + sysconf,
870 instRoot + sysconf + '.rpmsave')
871 # if it's an absolute symlink, just get it out of our way
872 elif (os.path.islink(instRoot + sysconf) and
873 os.readlink(instRoot + sysconf)[0] == '/'):
874 os.rename(instRoot + sysconf,
875 instRoot + sysconf + '.rpmsave')
876 f = open(instRoot + sysconf, 'w+')
877 f.write("boot=/dev/%s\n" %(grubTarget,))
878 if self.forceLBA32:
879 f.write("forcelba=1\n")
880 else:
881 f.write("forcelba=0\n")
882 f.close()
883
884 cmds = []
885 for bootDev in bootDevs:
886 gtPart = self.getMatchingPart(bootDev, grubTarget)
887 gtDisk = self.grubbyPartitionName(getDiskPart(gtPart)[0])
888 bPart = self.grubbyPartitionName(bootDev)
889 cmd = "root %s" % (bPart,)
890 cmds.append(cmd)
891
892 stage1Target = gtDisk
893 if target == "partition":
894 stage1Target = self.grubbyPartitionName(gtPart)
895
896 cmd = "install %s%s/stage1 d %s %s/stage2 p %s%s/grub.conf" % \
897 (forcelba, grubPath, stage1Target, grubPath, bPart, grubPath)
898 cmds.append(cmd)
899
900 if not justConfigFile:
901 log("GRUB commands:")
902 for cmd in cmds:
903 log("\t%s\n", cmd)
904
905 # copy the stage files over into /boot
906 rhpl.executil.execWithRedirect( "/sbin/grub-install",
907 ["/sbin/grub-install", "--just-copy"],
908 stdout = "/dev/tty5", stderr = "/dev/tty5",
909 root = instRoot)
910
911
912
913 # FIXME: hack to try to make sure everything is written to the disk
914 if cfPath == "/":
915 syncDataToDisk(bootDev, "/boot", instRoot)
916 else:
917 syncDataToDisk(bootDev, "/", instRoot)
918
919 # really install the bootloader
920 p = os.pipe()
921 for cmd in cmds:
922 os.write(p[1], cmd + '\n')
923 os.close(p[1])
924 rhpl.executil.execWithRedirect('/sbin/grub' ,
925 [ "grub", "--batch", "--no-floppy",
926 "--device-map=/boot/grub/device.map" ],
927 stdin = p[0],
928 stdout = "/dev/tty5", stderr = "/dev/tty5",
929 root = instRoot)
930 os.close(p[0])
931
932 return ""
933
934 def getMatchingPart(self, bootDev, target):
935 bootName, bootPartNum = getDiskPart(bootDev)
936 devices = self.getPhysicalDevices(target)
937 for device in devices:
938 name, partNum = getDiskPart(device)
939 if name == bootName:
940 return device
941 return devices[0]
942
943
944 def grubbyDiskName(self, name):
945 return "hd%d" % self.drivelist.index(name)
946
947 def grubbyPartitionName(self, dev):
948 (name, partNum) = getDiskPart(dev)
949 if partNum != None:
950 return "(%s,%d)" % (self.grubbyDiskName(name), partNum)
951 else:
952 return "(%s)" %(self.grubbyDiskName(name))
953
954
955 def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList,
956 chainList, defaultDev):
957 config = bootloaderInfo.getBootloaderConfig(self, instRoot, fsset,
958 bl, langs,
959 kernelList, chainList,
960 defaultDev)
961
962 liloTarget = bl.getDevice()
963
964 config.addEntry("boot", '/dev/' + liloTarget, replace = 0)
965 config.addEntry("map", "/boot/map", replace = 0)
966 config.addEntry("install", "/boot/boot.b", replace = 0)
967 message = "/boot/message"
968
969 if self.pure is not None and not self.useGrubVal:
970 config.addEntry("restricted", replace = 0)
971 config.addEntry("password", self.pure, replace = 0)
972
973
974 import language
975 for lang in language.expandLangs(langs.getDefault()):
976 fn = "/boot/message." + lang
977 if os.access(instRoot + fn, os.R_OK):
978 message = fn
979 break
980
981 if self.serial == 1:
982 # grab the 0-based number of the serial console device
983 unit = self.serialDevice[-1]
984 # FIXME: we should probably put some options, but lilo
985 # only supports up to 9600 baud so just use the defaults
986 # it's better than nothing :(
987 config.addEntry("serial=%s" %(unit,))
988 else:
989 # message screws up serial console
990 if os.access(instRoot + message, os.R_OK):
991 config.addEntry("message", message, replace = 0)
992
993 if not config.testEntry('lba32') and not config.testEntry('linear'):
994 if self.forceLBA32 or (bl.above1024 and
995 butil.getArch() != "x86_64" and
996 edd.detect()):
997 config.addEntry("lba32", replace = 0)
998 elif self.useLinear:
999 config.addEntry("linear", replace = 0)
1000 else:
1001 config.addEntry("nolinear", replace = 0)
1002
1003 return config
1004
1005 def writeLilo(self, instRoot, fsset, bl, langs, kernelList,
1006 chainList, defaultDev, justConfig):
1007 if not self.doUpgradeOnly and len(kernelList) >= 1:
1008 config = self.getBootloaderConfig(instRoot, fsset, bl, langs,
1009 kernelList, chainList, defaultDev)
1010 config.write(instRoot + self.configfile, perms = self.perms)
1011 elif self.doUpgradeOnly:
1012 # this is to work around the fact that older kernels don't
1013 # remove themselves from lilo.conf on upgrade
1014 # it's a really bad hack, probably also needs to happen on
1015 # other arches once they support upgradeonly
1016 config = LiloConfigFile ()
1017 if os.access (instRoot + self.configfile, os.R_OK):
1018 self.perms = os.stat(instRoot + self.configfile)[0] & 0777
1019 config.read (instRoot + self.configfile)
1020 # Remove any invalid entries that are in the file; we probably
1021 # just removed those kernels.
1022 for label in config.listImages():
1023 (fsType, sl, path, other) = config.getImage(label)
1024 if fsType == "other": continue
1025
1026 if not os.access(instRoot + sl.getPath(), os.R_OK):
1027 config.delImage(label)
1028
1029 # make sure that the default entry really exists. since
1030 # getDefault actually gets the entry for us, we'll get an
1031 # exception if it doesn't really exist.
1032 try:
1033 default = config.getDefault()
1034 except:
1035 try:
1036 config.delEntry("default")
1037 except:
1038 pass
1039
1040 config.write(instRoot + self.configfile, perms = self.perms)
1041
1042 # FIXME: do some syncs, just to make sure the config is written out
1043 import isys
1044 isys.sync()
1045 isys.sync()
1046 isys.sync()
1047
1048 if not justConfig:
1049 str = rhpl.executil.execWithRedirect('/sbin/lilo' ,
1050 ["/sbin/lilo", "-v"],
1051 stdout = "/dev/tty5",
1052 stderr = "/dev/tty5",
1053 root = instRoot)
1054 else:
1055 str = ""
1056
1057 return str
1058
1059 # this is a hackish function that depends on the way anaconda writes
1060 # out the grub.conf with a #boot= comment
1061 # XXX this falls into the category of self.doUpgradeOnly
1062 def upgradeGrub(self, instRoot, fsset, bl, langs, kernelList, chainList,
1063 defaultDev, justConfigFile):
1064 if justConfigFile:
1065 return ""
1066
1067 theDev = None
1068 for (fn, stanza) in [ ("/etc/sysconfig/grub", "boot="),
1069 ("/boot/grub/grub.conf", "#boot=") ]:
1070 try:
1071 f = open(instRoot + fn, "r")
1072 except:
1073 continue
1074
1075 # the following bits of code are straight from checkbootloader.py
1076 lines = f.readlines()
1077 f.close()
1078 for line in lines:
1079 if line.startswith(stanza):
1080 import checkbootloader
1081 theDev = checkbootloader.getBootDevString(line)
1082 break
1083 if theDev is not None:
1084 break
1085
1086 if theDev is None:
1087 # we could find the dev before, but can't now... cry about it
1088 return ""
1089
1090 # migrate info to /etc/sysconfig/grub
1091 sysconf = '/etc/sysconfig/grub'
1092 if not os.access(instRoot + sysconf, os.R_OK):
1093 f = open(instRoot + sysconf, "w+")
1094 f.write("boot=%s\n" %(theDev,))
1095 if self.forceLBA32:
1096 f.write("forcelba=1\n")
1097 else:
1098 f.write("forcelba=0\n")
1099 f.close()
1100
1101 # more suckage. grub-install can't work without a valid /etc/mtab
1102 # so we have to do shenanigans to get updated grub installed...
1103 # steal some more code above
1104 bootDev = fsset.getEntryByMountPoint("/boot")
1105 grubPath = "/grub"
1106 cfPath = "/"
1107 if not bootDev:
1108 bootDev = fsset.getEntryByMountPoint("/")
1109 grubPath = "/boot/grub"
1110 cfPath = "/boot/"
1111
1112 masterBootDev = bootDev.device.getDevice(asBoot = 0)
1113 if masterBootDev[0:2] == 'md':
1114 rootDevs = checkbootloader.getRaidDisks(masterBootDev, raidLevel=1,
1115 stripPart = 0)
1116 else:
1117 rootDevs = [masterBootDev]
1118
1119 if theDev[5:7] == 'md':
1120 stage1Devs = checkbootloader.getRaidDisks(theDev[5:], raidLevel=1)
1121 else:
1122 stage1Devs = [theDev[5:]]
1123
1124 for stage1Dev in stage1Devs:
1125 # cross fingers; if we can't find a root device on the same
1126 # hardware as this boot device, we just blindly hope the first
1127 # thing in the list works.
1128
1129 grubbyStage1Dev = self.grubbyPartitionName(stage1Dev)
1130
1131 grubbyRootPart = self.grubbyPartitionName(rootDevs[0])
1132
1133 for rootDev in rootDevs:
1134 testGrubbyRootDev = getDiskPart(rootDev)[0]
1135 testGrubbyRootDev = self.grubbyPartitionName(testGrubbyRootDev)
1136
1137 if grubbyStage1Dev == testGrubbyRootDev:
1138 grubbyRootPart = self.grubbyPartitionName(rootDev)
1139 break
1140
1141 cmd = "root %s\ninstall %s/stage1 d %s %s/stage2 p %s%s/grub.conf" \
1142 % (grubbyRootPart, grubPath, grubbyStage1Dev,
1143 grubPath, grubbyRootPart, grubPath)
1144
1145 if not justConfigFile:
1146 log("GRUB command %s", cmd)
1147
1148 # copy the stage files over into /boot
1149 rhpl.executil.execWithRedirect( "/sbin/grub-install",
1150 ["/sbin/grub-install", "--just-copy"],
1151 stdout = "/dev/tty5", stderr = "/dev/tty5",
1152 root = instRoot)
1153
1154 # get the stage files synced to disk
1155 import isys
1156 isys.sync()
1157 isys.sync()
1158 isys.sync()
1159
1160 # really install the bootloader
1161 p = os.pipe()
1162 os.write(p[1], cmd + '\n')
1163 os.close(p[1])
1164 rhpl.executil.execWithRedirect('/sbin/grub' ,
1165 [ "grub", "--batch", "--no-floppy",
1166 "--device-map=/boot/grub/device.map" ],
1167 stdin = p[0],
1168 stdout = "/dev/tty5", stderr = "/dev/tty5",
1169 root = instRoot)
1170 os.close(p[0])
1171
1172 return ""
1173
1174
1175 def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1176 defaultDev, justConfig, intf):
1177 # XXX HACK ALERT - see declaration above
1178 if self.doUpgradeOnly:
1179 if not self.useGrubVal:
1180 # we do upgrades sort of right for lilo...
1181 str = self.writeLilo(instRoot, fsset, bl, langs, kernelList,
1182 chainList, defaultDev,
1183 justConfig | (self.useGrubVal))
1184 else:
1185 self.upgradeGrub(instRoot, fsset, bl, langs, kernelList,
1186 chainList, defaultDev, justConfig)
1187
1188 # and the hacks continue. with 2.6, ide-scsi isn't used
1189 # anymore (#116622)
1190 import isys
1191 cdrw = isys.ideCdRwList()
1192 torem = []
1193 for device in cdrw:
1194 torem.append("%s=ide-scsi" %(device,))
1195
1196 for fn in ("/etc/lilo.conf", "/boot/grub/grub.conf",
1197 "/etc/lilo.conf.anaconda"):
1198 if not os.path.exists(instRoot + fn):
1199 continue
1200 f = open(instRoot + fn, "r")
1201 buf = f.read()
1202 f.close()
1203 for dev in torem:
1204 buf = buf.replace(dev, "")
1205 f = open(instRoot + fn, "w")
1206 f.write(buf)
1207 f.close()
1208 return
1209 if len(kernelList) < 1:
1210 self.noKernelsWarn(intf)
1211
1212 str = self.writeLilo(instRoot, fsset, bl, langs, kernelList,
1213 chainList, defaultDev,
1214 justConfig | (self.useGrubVal))
1215 str = self.writeGrub(instRoot, fsset, bl, langs, kernelList,
1216 chainList, defaultDev,
1217 justConfig | (not self.useGrubVal))
1218 # XXX move the lilo.conf out of the way if they're using GRUB
1219 # so that /sbin/installkernel does a more correct thing
1220 if self.useGrubVal and os.access(instRoot + '/etc/lilo.conf', os.R_OK):
1221 os.rename(instRoot + "/etc/lilo.conf",
1222 instRoot + "/etc/lilo.conf.anaconda")
1223
1224
1225
1226 def getArgList(self):
1227 args = bootloaderInfo.getArgList(self)
1228
1229 if not self.useGrubVal:
1230 args.append("--useLilo")
1231 if self.forceLBA32:
1232 args.append("--lba32")
1233 if not self.useLinear:
1234 args.append("--nolinear")
1235 if self.password:
1236 args.append("--md5pass=%s" %(self.password))
1237
1238
1239 # XXX add location of bootloader here too
1240
1241 return args
1242
1243 def __init__(self):
1244 bootloaderInfo.__init__(self)
1245 # XXX use checkbootloader to determine what to default to
1246 self.useGrubVal = 1
1247 self.kernelLocation = "/boot/"
1248 self.configfile = "/etc/lilo.conf"
1249 self.password = None
1250 self.pure = None
1251
1252 class s390BootloaderInfo(bootloaderInfo):
1253 def getBootloaderConfig(self, instRoot, fsset, bl, langs, kernelList,
1254 chainList, defaultDev):
1255 images = bl.images.getImages()
1256
1257 # on upgrade read in the lilo config file
1258 lilo = LiloConfigFile ()
1259 self.perms = 0600
1260 if os.access (instRoot + self.configfile, os.R_OK):
1261 self.perms = os.stat(instRoot + self.configfile)[0] & 0777
1262 lilo.read (instRoot + self.configfile)
1263 os.rename(instRoot + self.configfile,
1264 instRoot + self.configfile + '.rpmsave')
1265
1266 # Remove any invalid entries that are in the file; we probably
1267 # just removed those kernels.
1268 for label in lilo.listImages():
1269 (fsType, sl, path, other) = lilo.getImage(label)
1270 if fsType == "other": continue
1271
1272 if not os.access(instRoot + sl.getPath(), os.R_OK):
1273 lilo.delImage(label)
1274
1275 rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1276 if not rootDev:
1277 raise RuntimeError, "Installing zipl, but there is no root device"
1278
1279 if rootDev == defaultDev:
1280 lilo.addEntry("default", kernelList[0][0])
1281 else:
1282 lilo.addEntry("default", chainList[0][0])
1283
1284 for (label, longlabel, version) in kernelList:
1285 kernelTag = "-" + version
1286 kernelFile = self.kernelLocation + "vmlinuz" + kernelTag
1287
1288 try:
1289 lilo.delImage(label)
1290 except IndexError, msg:
1291 pass
1292
1293 sl = LiloConfigFile(imageType = "image", path = kernelFile)
1294
1295 initrd = booty.makeInitrd (kernelTag, instRoot)
1296
1297 sl.addEntry("label", label)
1298 if os.access (instRoot + initrd, os.R_OK):
1299 sl.addEntry("initrd",
1300 "%sinitrd%s.img" %(self.kernelLocation, kernelTag))
1301
1302 sl.addEntry("read-only")
1303 sl.addEntry("root", '/dev/' + rootDev)
1304 sl.addEntry("ipldevice", '/dev/' + rootDev[:-1])
1305
1306 if self.args.get():
1307 sl.addEntry('append', '"%s"' % self.args.get())
1308
1309 lilo.addImage (sl)
1310
1311 for (label, longlabel, device) in chainList:
1312 if ((not label) or (label == "")):
1313 continue
1314 try:
1315 (fsType, sl, path, other) = lilo.getImage(label)
1316 lilo.delImage(label)
1317 except IndexError:
1318 sl = LiloConfigFile(imageType = "other",
1319 path = "/dev/%s" %(device))
1320 sl.addEntry("optional")
1321
1322 sl.addEntry("label", label)
1323 lilo.addImage (sl)
1324
1325 # Sanity check #1. There could be aliases in sections which conflict
1326 # with the new images we just created. If so, erase those aliases
1327 imageNames = {}
1328 for label in lilo.listImages():
1329 imageNames[label] = 1
1330
1331 for label in lilo.listImages():
1332 (fsType, sl, path, other) = lilo.getImage(label)
1333 if sl.testEntry('alias'):
1334 alias = sl.getEntry('alias')
1335 if imageNames.has_key(alias):
1336 sl.delEntry('alias')
1337 imageNames[alias] = 1
1338
1339 # Sanity check #2. If single-key is turned on, go through all of
1340 # the image names (including aliases) (we just built the list) and
1341 # see if single-key will still work.
1342 if lilo.testEntry('single-key'):
1343 singleKeys = {}
1344 turnOff = 0
1345 for label in imageNames.keys():
1346 l = label[0]
1347 if singleKeys.has_key(l):
1348 turnOff = 1
1349 singleKeys[l] = 1
1350 if turnOff:
1351 lilo.delEntry('single-key')
1352
1353 return lilo
1354
1355 def writeChandevConf(self, bl, instroot): # S/390 only
1356 cf = "/etc/chandev.conf"
1357 self.perms = 0644
1358 if bl.args.chandevget():
1359 fd = os.open(instroot + "/etc/chandev.conf",
1360 os.O_WRONLY | os.O_CREAT)
1361 os.write(fd, "noauto\n")
1362 for cdev in bl.args.chandevget():
1363 os.write(fd,'%s\n' % cdev)
1364 os.close(fd)
1365 return ""
1366
1367
1368 def writeZipl(self, instRoot, fsset, bl, langs, kernelList, chainList,
1369 defaultDev, justConfigFile):
1370 images = bl.images.getImages()
1371 rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1372
1373 cf = '/etc/zipl.conf'
1374 self.perms = 0600
1375 if os.access (instRoot + cf, os.R_OK):
1376 self.perms = os.stat(instRoot + cf)[0] & 0777
1377 os.rename(instRoot + cf,
1378 instRoot + cf + '.rpmsave')
1379
1380 f = open(instRoot + cf, "w+")
1381
1382 f.write('[defaultboot]\n')
1383 f.write('default=' + kernelList[0][0] + '\n')
1384 f.write('target=%s\n' % (self.kernelLocation))
1385
1386 cfPath = "/boot/"
1387 for (label, longlabel, version) in kernelList:
1388 kernelTag = "-" + version
1389 kernelFile = "%svmlinuz%s" % (cfPath, kernelTag)
1390
1391 initrd = booty.makeInitrd (kernelTag, instRoot)
1392 f.write('[%s]\n' % (label))
1393 f.write('\timage=%s\n' % (kernelFile))
1394 if os.access (instRoot + initrd, os.R_OK):
1395 f.write('\tramdisk=%sinitrd%s.img\n' %(self.kernelLocation,
1396 kernelTag))
1397 realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
1398 f.write('\tparameters="root=%s' %(realroot,))
1399 if bl.args.get():
1400 f.write(' %s' % (bl.args.get()))
1401 f.write('"\n')
1402
1403 f.close()
1404
1405 if not justConfigFile:
1406 argv = [ "/sbin/zipl" ]
1407 rhpl.executil.execWithRedirect(argv[0], argv, root = instRoot,
1408 stdout = "/dev/stdout",
1409 stderr = "/dev/stderr")
1410
1411 return ""
1412
1413 def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1414 defaultDev, justConfig, intf):
1415 str = self.writeZipl(instRoot, fsset, bl, langs, kernelList,
1416 chainList, defaultDev,
1417 justConfig | (not self.useZiplVal))
1418 str = self.writeChandevConf(bl, instRoot)
1419
1420 def __init__(self):
1421 bootloaderInfo.__init__(self)
1422 self.useZiplVal = 1 # only used on s390
1423 self.kernelLocation = "/boot/"
1424 self.configfile = "/etc/zipl.conf"
1425
1426
1427 class alphaBootloaderInfo(bootloaderInfo):
1428 def wholeDevice (self, path):
1429 (device, foo) = getDiskPart(path)
1430 return device
1431
1432 def partitionNum (self, path):
1433 # getDiskPart returns part numbers 0-based; we need it one based
1434 # *sigh*
1435 (foo, partitionNumber) = getDiskPart(path)
1436 return partitionNumber + 1
1437
1438 # See if we would have to use MILO. MILO isn't supported by Red Hat.
1439 def useMilo (self):
1440 try:
1441 f = open ('/proc/cpuinfo', 'ro')
1442 except:
1443 return
1444 lines = f.readlines ()
1445 f.close()
1446 serial = ""
1447 for line in lines:
1448 if line.find("system serial number") != -1:
1449 serial = string.strip (string.split (line, ':')[1])
1450 break
1451
1452 if serial and len (serial) >= 4 and serial.startswith("MILO"):
1453 return 1
1454 else:
1455 return 0
1456
1457 def writeAboot(self, instRoot, fsset, bl, langs, kernelList,
1458 chainList, defaultDev, justConfig):
1459 # Get bootDevice and rootDevice
1460 rootDevice = fsset.getEntryByMountPoint("/").device.getDevice()
1461 if fsset.getEntryByMountPoint("/boot"):
1462 bootDevice = fsset.getEntryByMountPoint("/boot").device.getDevice()
1463 else:
1464 bootDevice = rootDevice
1465 bootnotroot = bootDevice != rootDevice
1466
1467 # If /etc/aboot.conf already exists we rename it
1468 # /etc/aboot.conf.rpmsave.
1469 if os.path.isfile(instRoot + self.configfile):
1470 os.rename (instRoot + self.configfile,
1471 instRoot + self.configfile + ".rpmsave")
1472
1473 # Then we create the necessary files. If the root device isn't
1474 # the boot device, we create /boot/etc/ where the aboot.conf
1475 # will live, and we create /etc/aboot.conf as a symlink to it.
1476 if bootnotroot:
1477 # Do we have /boot/etc ? If not, create one
1478 if not os.path.isdir (instRoot + '/boot/etc'):
1479 os.mkdir(instRoot + '/boot/etc', 0755)
1480
1481 # We install the symlink (/etc/aboot.conf has already been
1482 # renamed in necessary.)
1483 os.symlink("../boot" + self.configfile, instRoot + self.configfile)
1484
1485 cfPath = instRoot + "/boot" + self.configfile
1486 # Kernel path is set to / because a boot partition will
1487 # be a root on its own.
1488 kernelPath = '/'
1489 # Otherwise, we just need to create /etc/aboot.conf.
1490 else:
1491 cfPath = instRoot + self.configfile
1492 kernelPath = self.kernelLocation
1493
1494 # If we already have an aboot.conf, rename it
1495 if os.access (cfPath, os.R_OK):
1496 self.perms = os.stat(cfPath)[0] & 0777
1497 os.rename(cfPath, cfPath + '.rpmsave')
1498
1499 # Now we're going to create and populate cfPath.
1500 f = open (cfPath, 'w+')
1501 f.write ("# aboot default configurations\n")
1502
1503 if bootnotroot:
1504 f.write ("# NOTICE: You have a /boot partition. This means that\n")
1505 f.write ("# all kernel paths are relative to /boot/\n")
1506
1507 # bpn is the boot partition number.
1508 bpn = self.partitionNum(bootDevice)
1509 lines = 0
1510
1511 # We write entries line using the following format:
1512 # <line><bpn><kernel-name> root=<rootdev> [options]
1513 # We get all the kernels we need to know about in kernelList.
1514
1515 for (kernel, tag, kernelTag) in kernelList:
1516 kernelFile = "%svmlinuz-%s" %(kernelPath, kernelTag)
1517
1518 f.write("%d:%d%s" %(lines, bpn, kernelFile))
1519
1520 # See if we can come up with an initrd argument that exists
1521 initrd = booty.makeInitrd (kernelTag, instRoot)
1522 if os.access(instRoot + initrd, os.R_OK):
1523 f.write(" initrd=%sinitrd-%s.img" %(kernelPath, kernelTag))
1524
1525 realroot = getRootDevName(initrd, fsset, rootDevice, instRoot)
1526 f.write(" root=%s" %(realroot,))
1527
1528 args = self.args.get()
1529 if args:
1530 f.write(" %s" %(args,))
1531
1532 f.write("\n")
1533 lines = lines + 1
1534
1535 # We're done writing the file
1536 f.close ()
1537 del f
1538
1539 if not justConfig:
1540 # Now we're ready to write the relevant boot information. wbd
1541 # is the whole boot device, bdpn is the boot device partition
1542 # number.
1543 wbd = self.wholeDevice (bootDevice)
1544 bdpn = self.partitionNum (bootDevice)
1545
1546 # Calling swriteboot. The first argument is the disk to write
1547 # to and the second argument is a path to the bootstrap loader
1548 # file.
1549 args = ("swriteboot", ("/dev/%s" % wbd), "/boot/bootlx")
1550 log("swriteboot command: %s" %(args,))
1551 rhpl.executil.execWithRedirect ('/sbin/swriteboot', args,
1552 root = instRoot,
1553 stdout = "/dev/tty5",
1554 stderr = "/dev/tty5")
1555
1556 # Calling abootconf to configure the installed aboot. The
1557 # first argument is the disk to use, the second argument is
1558 # the number of the partition on which aboot.conf resides.
1559 # It's always the boot partition whether it's / or /boot (with
1560 # the mount point being omitted.)
1561 args = ("abootconf", ("/dev/%s" % wbd), str (bdpn))
1562 log("abootconf command: %s" %(args,))
1563 rhpl.executil.execWithRedirect ('/sbin/abootconf', args,
1564 root = instRoot,
1565 stdout = "/dev/tty5",
1566 stderr = "/dev/tty5")
1567
1568
1569 def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1570 defaultDev, justConfig, intf):
1571 if len(kernelList) < 1:
1572 self.noKernelsWarn(intf)
1573
1574 if self.useMilo():
1575 intf.messageWindow(_("MILO Not Supported"),
1576 "This system requires the support of MILO to " +
1577 "boot linux (MILO is not included in this " +
1578 "distribution.) The installation of the " +
1579 "bootloader can't be completed on this system.")
1580 # elif not justConfig FIXME.
1581 else:
1582 self.writeAboot(instRoot, fsset, bl, langs, kernelList,
1583 chainList, defaultDev, justConfig)
1584
1585 def __init__(self):
1586 bootloaderInfo.__init__(self)
1587 self.useGrubVal = 0
1588 self.configfile = "/etc/aboot.conf"
1589 # self.kernelLocation is already set to what we need.
1590 self.password = None
1591 self.pure = None
1592
1593
1594 class ppcBootloaderInfo(bootloaderInfo):
1595 def writeYaboot(self, instRoot, fsset, bl, langs, kernelList,
1596 chainList, defaultDev, justConfigFile):
1597
1598 from flags import flags
1599
1600 yabootTarget = '/dev/%s' %(bl.getDevice())
1601
1602 bootDev = fsset.getEntryByMountPoint("/boot")
1603 if bootDev:
1604 cf = "/boot/etc/yaboot.conf"
1605 cfPath = ""
1606 if not os.path.isdir(instRoot + "/boot/etc"):
1607 os.mkdir(instRoot + "/boot/etc")
1608 else:
1609 bootDev = fsset.getEntryByMountPoint("/")
1610 cfPath = "/boot"
1611 cf = "/etc/yaboot.conf"
1612 bootDev = bootDev.device.getDevice(asBoot = 1)
1613
1614 f = open(instRoot + cf, "w+")
1615 f.write("# yaboot.conf generated by anaconda\n\n")
1616
1617 f.write("boot=%s\n" %(yabootTarget,))
1618 f.write("init-message=Welcome to %s\\!\nHit <TAB> for boot options\n\n"
1619 %(butil.getProductName(),))
1620
1621 (name, partNum) = getDiskPart(bootDev)
1622 partno = partNum + 1 # 1 based
1623 f.write("partition=%s\n" %(partno,))
1624
1625 f.write("timeout=20\n")
1626 f.write("install=/usr/lib/yaboot/yaboot\n")
1627 f.write("delay=5\n")
1628
1629 if butil.getPPCMachine() == "PMac":
1630 f.write("magicboot=/usr/lib/yaboot/ofboot\n")
1631
1632 if butil.getPPCMachine() == "pSeries":
1633 f.write("nonvram\n")
1634
1635 if self.password:
1636 f.write("password=%s\n" %(self.password,))
1637 f.write("restricted\n")
1638
1639
1640 f.write("\n")
1641
1642 rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
1643
1644 for (label, longlabel, version) in kernelList:
1645 kernelTag = "-" + version
1646 kernelFile = "%s/vmlinuz%s" %(cfPath, kernelTag)
1647
1648 f.write("image=%s\n" %(kernelFile,))
1649 f.write("\tlabel=%s\n" %(label,))
1650 f.write("\tread-only\n")
1651
1652 initrd = booty.makeInitrd(kernelTag, instRoot)
1653 if os.access(instRoot + initrd, os.R_OK):
1654 f.write("\tinitrd=%s/initrd%s.img\n" %(cfPath,kernelTag))
1655
1656 append = "%s" %(self.args.get(),)
1657
1658 realroot = getRootDevName(initrd, fsset, rootDev, instRoot)
1659 if not realroot.startswith("LABEL="):
1660 f.write("\troot=%s\n" %(realroot,))
1661 else:
1662 if len(append) > 0:
1663 append = "%s root=%s" %(append,realroot)
1664 else:
1665 append = "root=%s" %(realroot,)
1666
1667 if len(append) > 0:
1668 f.write("\tappend=\"%s\"\n" %(append,))
1669 f.write("\n")
1670
1671 f.close()
1672 os.chmod(instRoot + cf, 0600)
1673
1674 # FIXME: hack to make sure things are written to disk
1675 import isys
1676 isys.sync()
1677 isys.sync()
1678 isys.sync()
1679
1680 ybinargs = [ "/sbin/mkofboot", "-f", "-C", cf ]
1681 if butil.getPPCMachine() == "pSeries":
1682 ybinargs.extend(["--filesystem", "raw"])
1683
1684
1685 log("running: %s" %(ybinargs,))
1686 if not flags.test:
1687 rhpl.executil.execWithRedirect(ybinargs[0],
1688 ybinargs,
1689 stdout = "/dev/tty5",
1690 stderr = "/dev/tty5",
1691 root = instRoot)
1692
1693 if (not os.access(instRoot + "/etc/yaboot.conf", os.R_OK) and
1694 os.access(instRoot + "/boot/etc/yaboot.conf", os.R_OK)):
1695 os.symlink("../boot/etc/yaboot.conf",
1696 instRoot + "/etc/yaboot.conf")
1697
1698 return ""
1699
1700 def setPassword(self, val, isCrypted = 1):
1701 # yaboot just handles the password and doesn't care if its crypted
1702 # or not
1703 self.password = val
1704
1705 def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1706 defaultDev, justConfig, intf):
1707 if len(kernelList) >= 1:
1708 str = self.writeYaboot(instRoot, fsset, bl, langs, kernelList,
1709 chainList, defaultDev, justConfig)
1710 else:
1711 self.noKernelsWarn(intf)
1712
1713 def __init__(self):
1714 bootloaderInfo.__init__(self)
1715 self.useYabootVal = 1
1716 self.kernelLocation = "/boot"
1717 self.configfile = "/etc/yaboot.conf"
1718
1719
1720 class iseriesBootloaderInfo(bootloaderInfo):
1721 def ddFile(self, inf, of, bs = 4096):
1722 src = os.open(inf, os.O_RDONLY)
1723 dest = os.open(of, os.O_WRONLY | os.O_CREAT)
1724 size = 0
1725
1726 buf = os.read(src, bs)
1727 while len(buf) > 0:
1728 size = size + len(buf)
1729 os.write(dest, buf)
1730 buf = os.read(src, bs)
1731
1732 os.close(src)
1733 os.close(dest)
1734
1735 return size
1736
1737 def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
1738 defaultDev, justConfig, intf):
1739 if len(kernelList) < 1:
1740 self.noKernelsWarn(intf)
1741 return
1742 if len(kernelList) > 1:
1743 # FIXME: how can this happen?
1744 log("more than one kernel on iSeries. bailing and just using "
1745 "the first")
1746
1747 # iseries is Weird (tm) -- here's the basic theory
1748 # a) have /boot/vmlinitrd-$(version)
1749 # b) copy default kernel to PReP partition
1750 # c) dd default kernel to /proc/iSeries/mf/C/vmlinux
1751 # d) set cmdline in /boot/cmdline-$(version)
1752 # e) copy cmdline to /proc/iSeries/mf/C/cmdline
1753 # f) set default side to 'C' i /proc/iSeries/mf/side
1754 # g) put default kernel and cmdline on side B too (#91038)
1755
1756 rootDevice = fsset.getEntryByMountPoint("/").device.getDevice()
1757
1758 # write our command line files
1759 for (kernel, tag, kernelTag) in kernelList:
1760 cmdFile = "%scmdline-%s" %(self.kernelLocation, kernelTag)
1761 initrd = "%sinitrd-%s.img" %(self.kernelLocation, kernelTag)
1762 realroot = getRootDevName(initrd, fsset, rootDevice, instRoot)
1763 f = open(instRoot + cmdFile, "w")
1764 f.write("ro root=%s" %(realroot,))
1765 if bl.args.get():
1766 f.write(" %s" %(bl.args.get(),))
1767 f.write("\n")
1768 f.close()
1769 os.chmod(instRoot + cmdFile, 0644)
1770
1771 kernel, tag, kernelTag = kernelList[0]
1772 kernelFile = "%svmlinitrd-%s" %(self.kernelLocation, kernelTag)
1773
1774 # write the kernel to the PReP partition since that's what
1775 # OS/400 will load as NWSSTG
1776 bootDev = bl.getDevice()
1777 if bootDev:
1778 log("Writing kernel %s to PReP partition %s" %(kernelFile,
1779 bootDev))
1780 try:
1781 self.ddFile(instRoot + kernelFile, "%s/dev/%s" %(instRoot,
1782 bootDev))
1783 except Exception, e:
1784 # FIXME: should this be more fatal
1785 log("Failed to write kernel: %s" %(e,))
1786 else:
1787 log("No PReP boot partition, not writing kernel for NWSSTG")
1788
1789
1790 # now, it's a lot faster to boot if we don't make people go back
1791 # into OS/400, so set up side C (used by default for NWSSTG) with
1792 # our current bits
1793 for side in ("C", "B"):
1794 log("Writing kernel and cmdline to side %s" %(side,))
1795 wrotekernel = 0
1796 try:
1797 self.ddFile(instRoot + kernelFile,
1798 "%s/proc/iSeries/mf/%s/vmlinux" %(instRoot, side))
1799 wrotekernel = 1
1800 except Exception, e:
1801 # FIXME: should this be more fatal?
1802 log("Failed to write kernel to side %s: %s" %(side, e))
1803
1804 if wrotekernel == 1:
1805 try:
1806 # blank it. ugh.
1807 f = open("%s/proc/iSeries/mf/%s/cmdline" %(instRoot, side),
1808 "w+")
1809 f.write(" " * 255)
1810 f.close()
1811
1812 self.ddFile("%s/%scmdline-%s" %(instRoot,
1813 self.kernelLocation,
1814 kernelTag),
1815 "%s/proc/iSeries/mf/%s/cmdline" %(instRoot,
1816 side))
1817 except Exception, e:
1818 log("Failed to write kernel command line to side %s: %s"
1819 %(side, e))
1820
1821 log("Setting default side to C")
1822 f = open(instRoot + "/proc/iSeries/mf/side", "w")
1823 f.write("C")
1824 f.close()
1825
1826 def __init__(self):
1827 bootloaderInfo.__init__(self)
1828 self.kernelLocation = "/boot/"
1829
1830
1831
1832 ###############
1833 # end of boot loader objects... these are just some utility functions used
1834
1835 # return (disk, partition number) eg ('hda', 1)
1836 def getDiskPart(dev):
1837 cut = len(dev)
1838 if (dev.startswith('rd/') or dev.startswith('ida/') or
1839 dev.startswith('cciss/')):
1840 if dev[-2] == 'p':
1841 cut = -1
1842 elif dev[-3] == 'p':
1843 cut = -2
1844 else:
1845 if dev[-2] in string.digits:
1846 cut = -2
1847 elif dev[-1] in string.digits:
1848 cut = -1
1849
1850 name = dev[:cut]
1851
1852 # hack off the trailing 'p' from /dev/cciss/*, for example
1853 if name[-1] == 'p':
1854 for letter in name:
1855 if letter not in string.letters and letter != "/":
1856 name = name[:-1]
1857 break
1858
1859 if cut < 0:
1860 partNum = int(dev[cut:]) - 1
1861 else:
1862 partNum = None
1863
1864 return (name, partNum)
1865
1866 # hackery to determine if we should do root=LABEL=/ or whatnot
1867 # as usual, knows too much about anaconda
1868 def getRootDevName(initrd, fsset, rootDev, instRoot):
1869 if not os.access(instRoot + initrd, os.R_OK):
1870 return "/dev/%s" % (rootDev,)
1871
1872 try:
1873 rootEntry = fsset.getEntryByMountPoint("/")
1874 if rootEntry.getLabel() is not None:
1875 return "LABEL=%s" %(rootEntry.getLabel(),)
1876 return "/dev/%s" %(rootDev,)
1877 except:
1878 return "/dev/%s" %(rootDev,)
1879

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