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