~ressu/+junk/xen-ubuntu

« back to all changes in this revision

Viewing changes to .pc/upstream-21375:179150c0b366/tools/pygrub/src/GrubConf.py

  • Committer: sami at haahtinen
  • Author(s): Bastian Blank
  • Date: 2011-01-12 13:01:40 UTC
  • Revision ID: sami@haahtinen.name-20110112130140-hqno31yosu4oovgw
Tags: 4.0.1-2
* Fix races in memory management.
* Make sure that frame-table compression leaves enough alligned.
* Disable XSAVE support. (closes: #595490)
* Check for dying domain instead of raising an assertion.
* Add C6 state with EOI errata for Intel.
* Make some memory management interrupt safe. Unsure if really needed.
* Raise bar for inter-socket migrations on mostly-idle systems.
* Fix interrupt handling for legacy routed interrupts.
* Allow to set maximal domain memory even during a running change.
* Support new partition name in pygrub. (closes: #599243)
* Fix some comparisions "< 0" that may be optimized away.
* Check for MWAIT support before using it.
* Fix endless loop on interrupts on Nehalem cpus.
* Don't crash upon direct GDT/LDT access. (closes: #609531)
  CVE-2010-4255  
* Don't loose timer ticks after domain restore.
* Reserve some space for IOMMU area in dom0. (closes: #608715)
* Fix hypercall arguments after trace callout.
* Fix some error paths in vtd support. Memory leak.
* Reinstate ACPI DMAR table.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# GrubConf.py - Simple grub.conf parsing
 
3
#
 
4
# Copyright 2009 Citrix Systems Inc.
 
5
# Copyright 2005-2006 Red Hat, Inc.
 
6
# Jeremy Katz <katzj@redhat.com>
 
7
#
 
8
# This software may be freely redistributed under the terms of the GNU
 
9
# general public license.
 
10
#
 
11
# You should have received a copy of the GNU General Public License
 
12
# along with this program; if not, write to the Free Software
 
13
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
14
#
 
15
 
 
16
import os, sys
 
17
import logging
 
18
import re
 
19
 
 
20
def grub_split(s, maxsplit = -1):
 
21
    eq = s.find('=')
 
22
    if eq == -1:
 
23
        return s.split(None, maxsplit)
 
24
 
 
25
    # see which of a space or tab is first
 
26
    sp = s.find(' ')
 
27
    tab = s.find('\t')
 
28
    if (tab != -1 and tab < sp) or (tab != -1 and sp == -1):
 
29
        sp = tab
 
30
 
 
31
    if eq != -1 and eq < sp or (eq != -1 and sp == -1):
 
32
        return s.split('=', maxsplit)
 
33
    else:
 
34
        return s.split(None, maxsplit)
 
35
 
 
36
def grub_exact_split(s, num):
 
37
    ret = grub_split(s, num - 1)
 
38
    if len(ret) < num:
 
39
        return ret + [""] * (num - len(ret))
 
40
    return ret
 
41
 
 
42
def get_path(s):
 
43
    """Returns a tuple of (GrubDiskPart, path) corresponding to string."""
 
44
    if not s.startswith('('):
 
45
        return (None, s)
 
46
    idx = s.find(')')
 
47
    if idx == -1:
 
48
        raise ValueError, "Unable to find matching ')'"
 
49
    d = s[:idx]
 
50
    return (GrubDiskPart(d), s[idx + 1:])
 
51
 
 
52
class GrubDiskPart(object):
 
53
    def __init__(self, str):
 
54
        if str.find(',') != -1:
 
55
            (self.disk, self.part) = str.split(",", 2)
 
56
        else:
 
57
            self.disk = str
 
58
            self.part = None
 
59
 
 
60
    def __repr__(self):
 
61
        if self.part is not None:
 
62
            return "d%dp%d" %(self.disk, self.part)
 
63
        else:
 
64
            return "d%d" %(self.disk,)
 
65
 
 
66
    def get_disk(self):
 
67
        return self._disk
 
68
    def set_disk(self, val):
 
69
        val = val.replace("(", "").replace(")", "")
 
70
        self._disk = int(val[2:])
 
71
    disk = property(get_disk, set_disk)
 
72
 
 
73
    def get_part(self):
 
74
        return self._part
 
75
    def set_part(self, val):
 
76
        if val is None:
 
77
            self._part = val
 
78
            return
 
79
        val = val.replace("(", "").replace(")", "")
 
80
        self._part = int(val)
 
81
    part = property(get_part, set_part)
 
82
 
 
83
class _GrubImage(object):
 
84
    def __init__(self, title, lines):
 
85
        self.reset(lines)
 
86
        self.title = title.strip()
 
87
 
 
88
    def __repr__(self):
 
89
        return ("title: %s\n" 
 
90
                "  root: %s\n"
 
91
                "  kernel: %s\n"
 
92
                "  args: %s\n"
 
93
                "  initrd: %s\n" %(self.title, self.root, self.kernel,
 
94
                                   self.args, self.initrd))
 
95
    def _parse(self, lines):
 
96
        map(self.set_from_line, lines)
 
97
 
 
98
    def reset(self, lines):
 
99
        self._root = self._initrd = self._kernel = self._args = None
 
100
        self.lines = []
 
101
        self._parse(lines)
 
102
 
 
103
    def set_root(self, val):
 
104
        self._root = GrubDiskPart(val)
 
105
    def get_root(self):
 
106
        return self._root
 
107
    root = property(get_root, set_root)
 
108
 
 
109
    def set_kernel(self, val):
 
110
        if val.find(" ") == -1:
 
111
            self._kernel = get_path(val)
 
112
            self._args = None
 
113
            return
 
114
        (kernel, args) = val.split(None, 1)
 
115
        self._kernel = get_path(kernel)
 
116
        self._args = args
 
117
    def get_kernel(self):
 
118
        return self._kernel
 
119
    def get_args(self):
 
120
        return self._args
 
121
    kernel = property(get_kernel, set_kernel)
 
122
    args = property(get_args)
 
123
 
 
124
    def set_initrd(self, val):
 
125
        self._initrd = get_path(val)
 
126
    def get_initrd(self):
 
127
        return self._initrd
 
128
    initrd = property(get_initrd, set_initrd)
 
129
 
 
130
class GrubImage(_GrubImage):
 
131
    def __init__(self, title, lines):
 
132
        _GrubImage.__init__(self, title, lines)
 
133
    
 
134
    def set_from_line(self, line, replace = None):
 
135
        (com, arg) = grub_exact_split(line, 2)
 
136
 
 
137
        if self.commands.has_key(com):
 
138
            if self.commands[com] is not None:
 
139
                setattr(self, self.commands[com], arg.strip())
 
140
            else:
 
141
                logging.info("Ignored image directive %s" %(com,))
 
142
        else:
 
143
            logging.warning("Unknown image directive %s" %(com,))
 
144
 
 
145
        # now put the line in the list of lines
 
146
        if replace is None:
 
147
            self.lines.append(line)
 
148
        else:
 
149
            self.lines.pop(replace)
 
150
            self.lines.insert(replace, line)
 
151
 
 
152
    # set up command handlers
 
153
    commands = { "root": "root",
 
154
                 "rootnoverify": "root",
 
155
                 "kernel": "kernel",
 
156
                 "initrd": "initrd",
 
157
                 "chainloader": None,
 
158
                 "module": None}
 
159
 
 
160
class _GrubConfigFile(object):
 
161
    def __init__(self, fn = None):
 
162
        self.filename = fn
 
163
        self.images = []
 
164
        self.timeout = -1
 
165
        self._default = 0
 
166
        self.passwordAccess = True
 
167
        self.passExc = None
 
168
 
 
169
        if fn is not None:
 
170
            self.parse()
 
171
 
 
172
    def parse(self, buf = None):
 
173
        raise RuntimeError, "unimplemented parse function"   
 
174
 
 
175
    def hasPasswordAccess(self):
 
176
        return self.passwordAccess
 
177
 
 
178
    def setPasswordAccess(self, val):
 
179
        self.passwordAccess = val
 
180
 
 
181
    def hasPassword(self):
 
182
        return hasattr(self, 'password')
 
183
 
 
184
    def checkPassword(self, password):
 
185
        # Always allow if no password defined in grub.conf
 
186
        if not self.hasPassword():
 
187
            return True
 
188
 
 
189
        pwd = getattr(self, 'password').split()
 
190
 
 
191
        # We check whether password is in MD5 hash for comparison
 
192
        if pwd[0] == '--md5':
 
193
            try:
 
194
                import crypt
 
195
                if crypt.crypt(password, pwd[1]) == pwd[1]:
 
196
                    return True
 
197
            except Exception, e:
 
198
                self.passExc = "Can't verify password: %s" % str(e)
 
199
                return False
 
200
 
 
201
        # ... and if not, we compare it as a plain text
 
202
        if pwd[0] == password:
 
203
            return True
 
204
 
 
205
        return False
 
206
 
 
207
    def set(self, line):
 
208
        (com, arg) = grub_exact_split(line, 2)
 
209
        if self.commands.has_key(com):
 
210
            if self.commands[com] is not None:
 
211
                setattr(self, self.commands[com], arg.strip())
 
212
            else:
 
213
                logging.info("Ignored directive %s" %(com,))
 
214
        else:
 
215
            logging.warning("Unknown directive %s" %(com,))
 
216
 
 
217
    def add_image(self, image):
 
218
        self.images.append(image)
 
219
 
 
220
    def _get_default(self):
 
221
        return self._default
 
222
    def _set_default(self, val):
 
223
        if val == "saved":
 
224
            self._default = 0
 
225
        else:
 
226
            self._default = int(val)
 
227
 
 
228
        if self._default < 0:
 
229
            raise ValueError, "default must be positive number"
 
230
    default = property(_get_default, _set_default)
 
231
 
 
232
    def set_splash(self, val):
 
233
        self._splash = get_path(val)
 
234
    def get_splash(self):
 
235
        return self._splash
 
236
    splash = property(get_splash, set_splash)
 
237
 
 
238
    # set up command handlers
 
239
    commands = { "default": "default",
 
240
                 "timeout": "timeout",
 
241
                 "fallback": "fallback",
 
242
                 "hiddenmenu": "hiddenmenu",
 
243
                 "splashimage": "splash",
 
244
                 "password": "password" }
 
245
    for c in ("bootp", "color", "device", "dhcp", "hide", "ifconfig",
 
246
              "pager", "partnew", "parttype", "rarp", "serial",
 
247
              "setkey", "terminal", "terminfo", "tftpserver", "unhide"):
 
248
        commands[c] = None
 
249
    del c
 
250
 
 
251
class GrubConfigFile(_GrubConfigFile):
 
252
    def __init__(self, fn = None):
 
253
        _GrubConfigFile.__init__(self,fn)
 
254
        
 
255
    def new_image(self, title, lines):
 
256
        return GrubImage(title, lines)
 
257
 
 
258
    def parse(self, buf = None):
 
259
        if buf is None:
 
260
            if self.filename is None:
 
261
                raise ValueError, "No config file defined to parse!"
 
262
 
 
263
            f = open(self.filename, 'r')
 
264
            lines = f.readlines()
 
265
            f.close()
 
266
        else:
 
267
            lines = buf.split("\n")
 
268
 
 
269
        img = None
 
270
        title = ""
 
271
        for l in lines:
 
272
            l = l.strip()
 
273
            # skip blank lines
 
274
            if len(l) == 0:
 
275
                continue
 
276
            # skip comments
 
277
            if l.startswith('#'):
 
278
                continue
 
279
            # new image
 
280
            if l.startswith("title"):
 
281
                if img is not None:
 
282
                    self.add_image(GrubImage(title, img))
 
283
                img = []
 
284
                title = l[6:]
 
285
                continue
 
286
                
 
287
            if img is not None:
 
288
                img.append(l)
 
289
                continue
 
290
 
 
291
            (com, arg) = grub_exact_split(l, 2)
 
292
            if self.commands.has_key(com):
 
293
                if self.commands[com] is not None:
 
294
                    setattr(self, self.commands[com], arg.strip())
 
295
                else:
 
296
                    logging.info("Ignored directive %s" %(com,))
 
297
            else:
 
298
                logging.warning("Unknown directive %s" %(com,))
 
299
                
 
300
        if img:
 
301
            self.add_image(GrubImage(title, img))
 
302
 
 
303
        if self.hasPassword():
 
304
            self.setPasswordAccess(False)
 
305
 
 
306
def grub2_handle_set(arg):
 
307
    (com,arg) = grub_split(arg,2)
 
308
    com="set:" + com
 
309
    m = re.match("([\"\'])(.*)\\1", arg)
 
310
    if m is not None:
 
311
        arg=m.group(2) 
 
312
    return (com,arg)
 
313
 
 
314
class Grub2Image(_GrubImage):
 
315
    def __init__(self, title, lines):
 
316
        _GrubImage.__init__(self, title, lines)
 
317
 
 
318
    def set_from_line(self, line, replace = None):
 
319
        (com, arg) = grub_exact_split(line, 2)
 
320
 
 
321
        if com == "set":
 
322
            (com,arg) = grub2_handle_set(arg)
 
323
            
 
324
        if self.commands.has_key(com):
 
325
            if self.commands[com] is not None:
 
326
                setattr(self, self.commands[com], arg.strip())
 
327
            else:
 
328
                logging.info("Ignored image directive %s" %(com,))
 
329
        elif com.startswith('set:'):
 
330
            pass
 
331
        else:
 
332
            logging.warning("Unknown image directive %s" %(com,))
 
333
 
 
334
        # now put the line in the list of lines
 
335
        if replace is None:
 
336
            self.lines.append(line)
 
337
        else:
 
338
            self.lines.pop(replace)
 
339
            self.lines.insert(replace, line)
 
340
                
 
341
    commands = {'set:root': 'root',
 
342
                'linux': 'kernel',
 
343
                'initrd': 'initrd',
 
344
                'echo': None,
 
345
                'insmod': None,
 
346
                'search': None}
 
347
    
 
348
class Grub2ConfigFile(_GrubConfigFile):
 
349
    def __init__(self, fn = None):
 
350
        _GrubConfigFile.__init__(self, fn)
 
351
       
 
352
    def new_image(self, title, lines):
 
353
        return Grub2Image(title, lines)
 
354
 
 
355
    def parse(self, buf = None):
 
356
        if buf is None:
 
357
            if self.filename is None:
 
358
                raise ValueError, "No config file defined to parse!"
 
359
 
 
360
            f = open(self.filename, 'r')
 
361
            lines = f.readlines()
 
362
            f.close()
 
363
        else:
 
364
            lines = buf.split("\n")
 
365
 
 
366
        in_function = False
 
367
        img = None
 
368
        title = ""
 
369
        for l in lines:
 
370
            l = l.strip()
 
371
            # skip blank lines
 
372
            if len(l) == 0:
 
373
                continue
 
374
            # skip comments
 
375
            if l.startswith('#'):
 
376
                continue
 
377
 
 
378
            # skip function declarations
 
379
            if l.startswith('function'):
 
380
                in_function = True
 
381
                continue
 
382
            if in_function:
 
383
                if l.startswith('}'):
 
384
                    in_function = False
 
385
                continue
 
386
 
 
387
            # new image
 
388
            title_match = re.match('^menuentry ["\'](.*)["\'] (.*){', l)
 
389
            if title_match:
 
390
                if img is not None:
 
391
                    raise RuntimeError, "syntax error: cannot nest menuentry (%d %s)" % (len(img),img)
 
392
                img = []
 
393
                title = title_match.group(1)
 
394
                continue
 
395
            
 
396
            if l.startswith("}"):
 
397
                if img is None:
 
398
                    raise RuntimeError, "syntax error: closing brace without menuentry"
 
399
 
 
400
                self.add_image(Grub2Image(title, img))
 
401
                img = None
 
402
                continue
 
403
 
 
404
            if img is not None:
 
405
                img.append(l)
 
406
                continue
 
407
 
 
408
            (com, arg) = grub_exact_split(l, 2)
 
409
        
 
410
            if com == "set":
 
411
                (com,arg) = grub2_handle_set(arg)
 
412
                
 
413
            if self.commands.has_key(com):
 
414
                if self.commands[com] is not None:
 
415
                    setattr(self, self.commands[com], arg.strip())
 
416
                else:
 
417
                    logging.info("Ignored directive %s" %(com,))
 
418
            elif com.startswith('set:'):
 
419
                pass
 
420
            else:
 
421
                logging.warning("Unknown directive %s" %(com,))
 
422
            
 
423
        if img is not None:
 
424
            raise RuntimeError, "syntax error: end of file with open menuentry(%d %s)" % (len(img),img)
 
425
 
 
426
        if self.hasPassword():
 
427
            self.setPasswordAccess(False)
 
428
 
 
429
    commands = {'set:default': 'default',
 
430
                'set:root': 'root',
 
431
                'set:timeout': 'timeout',
 
432
                'terminal': None,
 
433
                'insmod': None,
 
434
                'load_env': None,
 
435
                'save_env': None,
 
436
                'search': None,
 
437
                'if': None,
 
438
                'fi': None,
 
439
                }
 
440
        
 
441
if __name__ == "__main__":
 
442
    if sys.argv < 3:
 
443
        raise RuntimeError, "Need a grub version (\"grub\" or \"grub2\") and a grub.conf or grub.cfg to read"
 
444
    if sys.argv[1] == "grub":
 
445
        g = GrubConfigFile(sys.argv[2])
 
446
    elif sys.argv[1] == "grub2":
 
447
        g = Grub2ConfigFile(sys.argv[2])
 
448
    else:
 
449
        raise RuntimeError, "Unknown config type %s" % sys.argv[1]
 
450
    for i in g.images:
 
451
        print i #, i.title, i.root, i.kernel, i.args, i.initrd