allow default settings in the mainboard file
[coreboot.git] / util / newconfig / config.g
1 import sys
2 import os
3 import re
4 import string
5 import types
6
7 import traceback
8
9 warnings = 0
10 errors = 0
11
12 target_dir = ''
13 target_name = ''
14 treetop = ''
15 global_options = {}
16 global_options_by_order = []
17 global_option_values = {}
18 global_uses_options = {}
19 romimages = {}
20 buildroms = []
21 curimage = 0
22 alloptions = 0 # override uses at top level
23
24 local_path = re.compile(r'^\.')
25 include_pattern = re.compile(r'%%([^%]+)%%')
26
27 # the cpu type for this mainboard
28 cpu_type = 0
29
30 # -----------------------------------------------------------------------------
31 #                    Utility Classes
32 # -----------------------------------------------------------------------------
33
34 class stack:
35         """Used to keep track of the current part or dir"""
36         class __stack_iter:
37                 def __init__ (self, stack):
38                         self.index = 0
39                         self.len = len(stack)
40                         self.stack = stack
41
42                 def __iter__ (self):
43                         return self
44
45                 def next (self):
46                         if (self.index < self.len):
47                                 s = self.stack[self.index]
48                                 self.index = self.index + 1
49                                 return s
50                         raise StopIteration
51
52         def __init__ (self):
53                 self.stack = []
54
55         def __len__ (self):
56                 return len(self.stack)
57
58         def __getitem__ (self, i):
59                 return self.stack[i]
60
61         def __iter__ (self):
62                 return self.__stack_iter(self.stack)
63
64         def push(self, part):
65                 self.stack.append(part)
66
67         def pop(self):
68                 try:
69                         return self.stack.pop()
70                 except IndexError:
71                         return 0
72
73         def tos(self):
74                 try:
75                         return self.stack[-1]
76                 except IndexError:
77                         return 0
78
79         def empty(self):
80                 return (len(self.stack) == 0)
81 partstack = stack()
82 dirstack = stack()
83
84 class debug_info:
85         none = 0
86         gencode = 1
87         dumptree = 2
88         object = 3
89         dict = 4
90         statement = 5
91         dump = 6
92
93         def __init__(self, *level):
94                 self.__level = level
95
96         def setdebug(self, *level):
97                 self.__level = level
98
99         def level(self, level):
100                 return level in self.__level
101
102         def info(self, level, str):
103                 if level in self.__level:
104                         print str
105
106 global debug
107 debug = debug_info(debug_info.none)
108
109 # -----------------------------------------------------------------------------
110 #                    Error Handling
111 # -----------------------------------------------------------------------------
112
113 class location:
114         """Used to keep track of our current location while parsing
115         configuration files"""
116         class __place:
117                 def __init__(self, file, line, command):
118                         self.file = file
119                         self.line = line
120                         self.command = command
121                 def next_line(self, command):
122                         self.line = self.line + 1
123                         self.command = command
124                 def at(self):
125                         return "%s:%d" % (self.file, self.line)
126         
127         def __init__ (self):
128                 self.stack = stack()
129
130         def __str__ (self):
131                 s = ''
132                 for p in self.stack:
133                         if (s == ''):
134                                 s = p.at()
135                         else:
136                                 s = s + '\n' + p.at()
137                 return s
138
139         def file(self):
140                 return self.stack.tos().file
141
142         def line(self):
143                 return self.stack.tos().line
144
145         def command(self):
146                 return self.stack.tos().command
147
148         def push(self, file):
149                 self.stack.push(self.__place(os.path.normpath(file), 0, ""))
150
151         def pop(self):
152                 self.stack.pop()
153
154         def next_line(self, command):
155                 self.stack.tos().next_line(command)
156
157         def at(self):
158                 return self.stack.tos().at()
159 loc = location()
160
161 def error(string):      
162         """Print error message"""
163         global errors, loc
164         errors = errors + 1
165         print "===> ERROR: %s" % string
166         print "%s" % loc
167
168 def fatal(string):      
169         """Print error message and exit"""
170         error(string)
171         exitiferrors()
172
173 def warning(string):
174         """Print warning message"""
175         global warnings, loc
176         warnings = warnings + 1
177         print "===> WARNING: %s" % string
178         print "%s" % loc
179
180 def exitiferrors():
181         """Exit parser if an error has been encountered"""
182         if (errors != 0):
183                 sys.exit(1)
184
185 def safe_open(file, mode):
186         try:
187                 return open(file, mode)
188         except IOError:
189                 fatal("Could not open file \"%s\"" % file)
190
191 # -----------------------------------------------------------------------------
192 #                    Main classes
193 # -----------------------------------------------------------------------------
194
195 class romimage:
196         """A rom image is the ultimate goal of linuxbios"""
197         def __init__ (self, name):
198                 # name of this rom image
199                 self.name = name
200
201                 # set by 'arch' directive
202                 self.arch = ''
203
204                 # set by 'payload' directive
205                 self.payload = ''
206
207                 # set by 'init' directive
208                 self.initfile = ''
209
210                 # make rules added by 'makerule' directive
211                 self.makebaserules = {}
212
213                 # object files added by 'object' directive
214                 self.objectrules = {}
215
216                 # init object files added by 'initobject' directive
217                 self.initobjectrules = {}
218
219                 # driver files added by 'drive' directive
220                 self.driverrules = {}
221
222                 # loader scripts added by 'ldscript' directive
223                 self.ldscripts = []
224
225                 # user defines added by 'makedefine' directive
226                 self.userdefines = []
227
228                 # files to be included in crt0.S
229                 self.initincludes = {}
230
231                 # as above, but order is preserved
232                 self.initincludesorder = []
233
234                 # transitional flag to support old crtinclude format
235                 self.useinitincludes = 0
236
237                 # instance counter for parts
238                 self.partinstance = 0
239
240                 # chip config files included by the 'config' directive
241                 self.configincludes = {}
242
243                 # root of part tree
244                 self.root = 0
245
246                 # name of target directory specified by 'target' directive
247                 self.target_dir = ''
248
249                 # option values set in rom image
250                 self.values = {}
251
252         def getname(self):
253                 return self.name
254
255         def getvalues(self):
256                 return self.values
257
258         def setarch(self, arch):
259                 self.arch = arch
260
261         def setpayload(self, payload):
262                 self.payload = payload
263
264         def setinitfile(self, initfile):
265                 self.initfile = initfile
266
267         def getinitfile(self):
268                 return self.initfile
269
270         def addmakerule(self, id):
271                 o = getdict(self.makebaserules, id)
272                 if (o):
273                         warning("rule %s previously defined" % id)
274                 o = makerule(id)
275                 setdict(self.makebaserules, id, o)
276
277         def getmakerules(self):
278                 return self.makebaserules
279
280         def getmakerule(self, id):
281                 o = getdict(self.makebaserules, id)
282                 if (o):
283                         return o
284                 fatal("No such make rule \"%s\"" % id);
285
286         def addmakeaction(self, id, str):
287                 o = getdict(self.makebaserules, id)
288                 if (o):
289                         a = dequote(str)
290                         o.addaction(a)
291                         return
292                 fatal("No such rule \"%s\" for addmakeaction" % id);
293
294         def addmakedepend(self, id, str):
295                 o = getdict(self.makebaserules, id)
296                 if (o):
297                         a = dequote(str)
298                         o.adddependency(a)
299                         return
300                 fatal("No such rule \"%s\" for addmakedepend" % id);
301
302         # this is called with an an object name. 
303         # the easiest thing to do is add this object to the current 
304         # component.
305         # such kludgery. If the name starts with '.' then make the 
306         # dependency be on ./thing.x gag me.
307         def addobjectdriver(self, dict, object_name):
308                 global dirstack
309                 suffix = object_name[-2:]
310                 if (suffix == '.o'):
311                         suffix = '.c'
312                 base = object_name[:-2]
313                 type = object_name[-1:]
314                 if (object_name[0] == '.'):
315                         source = base + suffix
316                 else:
317                         source = os.path.join(dirstack.tos(), base + suffix)
318                 object = base + '.o'
319                 debug.info(debug.object, "add object %s source %s" % (object_name, source))
320                 l = getdict(dict, base)
321                 if (l):
322                         warning("object/driver %s previously defined" % base)
323                 setdict(dict, base, [object, source, type, base])
324
325         def addinitobjectrule(self, name):
326                 self.addobjectdriver(self.initobjectrules, name)
327
328         def addobjectrule(self, name):
329                 self.addobjectdriver(self.objectrules, name)
330
331         def adddriverrule(self, name):
332                 self.addobjectdriver(self.driverrules, name)
333
334         def getinitobjectrules(self):
335                 return self.initobjectrules
336
337         def getinitobjectrule(self, name):
338                 o = getdict(self.initobjectrules, name)
339                 if (o):
340                         return o
341                 fatal("No such init object rule \"%s\"" % name);
342
343         def getobjectrules(self):
344                 return self.objectrules
345
346         def getobjectrule(self, name):
347                 o = getdict(self.objectrules, name)
348                 if (o):
349                         return o
350                 fatal("No such object rule \"%s\"" % name);
351
352         def getdriverrules(self):
353                 return self.driverrules
354
355         def getdriverrule(self, name):
356                 o = getdict(self.driverrules, name)
357                 if (o):
358                         return o
359                 fatal("No such driver rule \"%s\"" % name);
360
361         def addldscript(self, path):
362                 self.ldscripts.append(path)
363
364         def getldscripts(self):
365                 return self.ldscripts
366
367         def adduserdefine(self, str):
368                 self.userdefines.append(str)
369
370         def getuserdefines(self):
371                 return self.userdefines
372
373         def addinitinclude(self, str, path):
374                 if (str != 0):
375                         self.useinitincludes = 1
376
377                 debug.info(debug.object, "ADDCRT0: %s -> %s" % (str, path))
378                 o = getdict(self.initincludes, path)
379                 if (o):
380                         warning("Warning, init include for %s previously defined" % path)
381                 o = initinclude(str, path)
382                 setdict(self.initincludes, path, o)
383                 self.initincludesorder.append(path)
384
385         def getinitincludes(self):
386                 return self.initincludesorder
387
388         def getinitinclude(self, path):
389                 o = getdict(self.initincludes, path)
390                 if (o):
391                         return o
392                 fatal("No such init include \"%s\"" % path);
393
394         def addconfiginclude(self, part, path):
395                 setdict(self.configincludes, part, path)
396
397         def getconfigincludes(self):
398                 return self.configincludes
399
400         def getincludefilename(self):
401                 if (self.useinitincludes):
402                         return "crt0.S"
403                 else:
404                         return "crt0_includes.h"
405         
406         def newformat(self):
407                 return self.useinitincludes
408
409         def numparts(self):
410                 return self.partinstance
411
412         def newpartinstance(self):
413                 i = self.partinstance
414                 self.partinstance = self.partinstance + 1
415                 return i
416
417         def setroot(self, part):
418                 self.root = part
419
420         def getroot(self):
421                 return self.root
422
423         def settargetdir(self, path):
424                 self.targetdir = path
425
426         def gettargetdir(self):
427                 return self.targetdir
428
429 class buildrom:
430         """A buildrom statement"""
431         def __init__ (self, filename, size, roms):
432                 self.name = filename
433                 self.size = size
434                 self.roms = roms
435         
436         def __len__ (self):
437                 return len(self.roms)
438
439         def __getitem__(self,i):
440                 return self.roms[i]
441
442 class initinclude:
443         """include file for initialization code"""
444         def __init__ (self, str, path):
445                 self.string = str
446                 self.path = path
447
448         def getstring(self):
449                 return self.string
450
451         def getpath(self):
452                 return self.path
453
454 class makerule:
455         """Rule to be included in Makefile"""
456         def __init__ (self, target):
457                 self.target = target
458                 self.dependency = []
459                 self.actions = []
460
461         def addaction(self, action):
462                 self.actions.append(action)
463
464         def adddependency(self, dependency):
465                 self.dependency.append(dependency)
466
467         def gtarget(self):
468                 return self.target
469
470         def gdependency(self):
471                 return self.dependency
472
473         def gaction(self):
474                 return self.actions
475
476 class option:
477         """Configuration option"""
478         def __init__ (self, name):
479                 self.name = name        # name of option
480                 self.loc = 0            # current location
481                 self.set = 0            # option has been set
482                 self.used = 0           # option has been set
483                 self.default = 0        # option has default value (otherwise
484                                         # it is undefined)
485                 self.comment = ''       # description of option
486                 self.exportable = 0     # option is able to be exported
487                 self.exported = 0       # option is exported
488                 self.defined = 0        # option has a value
489                 self.format = '%s'      # option print format
490
491         def setvalue(self, value, values, loc):
492                 self.set = 1
493                 self.defined = 1
494                 self.loc = loc
495                 #self.value = value
496                 setdict(values, self.name, value)
497
498         def getvalue(self, image, values):
499                 global curimage
500                 v = getdict(values, self.name)
501                 if (v == 0):
502                         return 0
503                 val = v.contents()
504                 if (not (type(val) is types.StringType)):
505                         return v
506                 if (val == '' or val[0] != '{'):
507                         return v
508                 s = curimage
509                 curimage = image
510                 val = parse('delexpr', val)
511                 curimage = s
512                 # TODO: need to check for parse errors!
513                 return option_value(val)
514
515         def setdefault(self, value, loc):
516                 global global_option_values
517                 if (self.default):
518                         fatal("default value for %s already set" % self.name)
519                 setdict(global_option_values, self.name, value)
520                 self.defined = 1
521                 self.default = 1
522                 self.loc = loc
523
524         def setnodefault(self, loc):
525                 self.default = 1
526                 self.defined = 0
527                 self.loc = loc
528
529         def where(self):
530                 return self.loc
531
532         def setcomment(self, comment, loc):
533                 if (self.comment != ''):
534                         print "%s: " % self.name
535                         print "Attempt to modify comment at %s" % loc 
536                         return
537                 self.comment = comment
538
539         def setexportable(self):
540                 self.exportable = 1
541
542         def setexported(self):
543                 self.exportable = 1
544                 self.exported = 1
545
546         def setnoexport(self):
547                 self.exportable = 0
548                 self.exported = 0
549
550         def setformat(self, fmt):
551                 self.format = fmt
552
553         def getformat(self):
554                 return self.format
555
556         def setused(self):
557                 if (self.exportable):
558                         self.exported = 1
559                 self.used = 1
560
561         def isexported(self):
562                 return (self.exported and self.defined)
563
564 #       def isdefined(self):
565 #               return (self.defined)
566
567         def isset(self):
568                 return (self.set)
569
570 #       def isused(self):
571 #               return (self.used)
572
573 class option_value:
574         """Value of a configuration option"""
575         def __init__(self, value):
576                 self.value = value
577
578         def contents(self):
579                 return self.value
580
581 class partobj:
582         """A configuration part"""
583         def __init__ (self, image, dir, parent, part, type_name, instance_name):
584                 debug.info(debug.object, "partobj dir %s parent %s part %s" \
585                                 % (dir, parent, part))
586
587                 # romimage that is configuring this part
588                 self.image = image
589
590                 # links for static device tree
591                 self.children = 0
592                 self.siblings = 0
593
594                 # list of init code files
595                 self.initcode = []
596
597                 # initializers for static device tree
598                 self.registercode = {}
599
600                 # part name
601                 self.part = part
602
603                 # type name of this part
604                 self.type_name = type_name
605
606                 # object files needed to build this part
607                 self.objects = []
608
609                 # directory containg part files
610                 self.dir = dir
611
612                 # instance number, used to distinguish anonymous
613                 # instances of this part
614                 self.instance = image.newpartinstance()
615                 debug.info(debug.object, "INSTANCE %d" % self.instance)
616
617                 # Options used by this part
618                 self.uses_options = {}
619
620                 # Name of chip config file (0 if not needed)
621                 self.chipconfig = 0
622
623                 # Flag to indicate that we have generated type
624                 # definitions for this part (only want to do it once)
625                 self.done_types = 0
626
627                 # Path to the device
628                 self.path = ""
629                 
630                 # If no instance name is supplied then generate
631                 # a unique name
632                 if (instance_name == 0):
633                         self.instance_name = self.type_name + \
634                                         "_dev%d" % self.instance
635                         self.config_name = "%s_config_%d" \
636                                         % (self.type_name, self.instance)
637                 else:
638                         self.instance_name = instance_name
639                         self.config_name = "%s_config" % self.instance_name
640                 
641                 # Link this part into the tree
642                 if (parent):
643                         debug.info(debug.gencode, "add to parent")
644                         self.parent   = parent
645                         # add current child as my sibling, 
646                         # me as the child.
647                         if (parent.children):
648                                 debug.info(debug.gencode, "add %s (%d) as sibling" % (parent.children.dir, parent.children.instance))
649                                 youngest = parent.children;
650                                 while(youngest.siblings):
651                                         youngest = youngest.siblings
652                                 youngest.siblings = self
653                         else:
654                                 parent.children = self
655                 else:
656                         self.parent = self
657
658         def dumpme(self, lvl):
659                 """Dump information about this part for debugging"""
660                 print "%d: part %s" % (lvl, self.part)
661                 print "%d: instance %d" % (lvl, self.instance)
662                 print "%d: dir %s" % (lvl,self.dir)
663                 print "%d: name %s" % (lvl,self.name)
664                 print "%d: parent %s" % (lvl,self.parent.part)
665                 print "%d: parent dir %s" % (lvl,self.parent.dir)
666                 if (self.children):
667                         print "%d: child %s" % (lvl, self.children.dir)
668                 if (self.siblings):
669                         print "%d: siblings %s" % (lvl, self.siblings.dir)
670                 print "%d: initcode " % lvl
671                 for i in self.initcode:
672                         print "\t%s" % i
673                 print "%d: registercode " % lvl
674                 for f, v in self.registercode.items():
675                         print "\t%s = %s" % (f, v)
676                 print "\n"
677
678         def gencode(self, file, pass_num):
679                 """Generate static initalizer code for this part. Two passes
680                 are used - the first generates type information, and the second
681                 generates instance information"""
682                 if (pass_num == 0):
683                         if (self.instance):
684                                 file.write("struct chip %s;\n" \
685                                         % self.instance_name)
686                         else:
687                                 file.write("struct chip static_root;\n")
688                         return
689                 if (self.chipconfig):
690                         debug.info(debug.gencode, "gencode: chipconfig(%d)" % \
691                                         self.instance)
692                         file.write("struct %s_config %s" % (self.type_name ,\
693                                         self.config_name))
694                         if (self.registercode):
695                                 file.write("\t= {\n")
696                                 for f, v in self.registercode.items():
697                                         file.write( "\t.%s = %s,\n" % (f, v))
698                                 file.write("};\n")
699                         else:
700                                 file.write(";")
701                         file.write("\n");
702                 if (self.instance):
703                         file.write("struct chip %s = {\n" % self.instance_name)
704                 else:
705                         file.write("struct chip static_root = {\n")
706                 file.write("\t/* %s %s */\n" % (self.part, self.dir))
707                 if (self.path != ""):
708                         file.write("\t.path = { %s\n\t},\n" % (self.path) );
709                 if (self.siblings):
710                         debug.info(debug.gencode, "gencode: siblings(%d)" \
711                                 % self.siblings.instance)
712                         file.write("\t.next = &%s,\n" \
713                                 % self.siblings.instance_name)
714                 else:
715                         file.write("\t.next = 0,\n")
716                 if (self.children):
717                         debug.info(debug.gencode, "gencode: children(%d)" \
718                                 % self.children.instance)
719                         file.write("\t.children = &%s,\n" \
720                                 % self.children.instance_name)
721                 else:
722                         file.write("\t.children = 0,\n")
723                 if (self.chipconfig):
724                         # set the pointer to the structure for all this
725                         # type of part
726                         file.write("\t.control= &%s_control,\n" % \
727                                         self.type_name )
728                         # generate the pointer to the isntance
729                         # of the chip struct
730                         file.write("\t.chip_info = (void *) &%s,\n" \
731                                         % self.config_name)
732                 else:
733                         file.write("\t.control= 0,\n")
734                         file.write("\t.chip_info= 0,\n")
735                 file.write("};\n")
736                 
737         def addinit(self, code):
738                 """Add init file to this part"""
739                 self.initcode.append(code)
740                 
741         def addconfig(self, path):
742                 """Add chip config file to this part"""
743                 self.chipconfig = os.path.join(self.dir, path)
744                 self.image.addconfiginclude(self.type_name, self.chipconfig)
745
746         def addregister(self, field, value):
747                 """Register static initialization information"""
748                 field = dequote(field)
749                 value = dequote(value)
750                 setdict(self.registercode, field, value)
751
752         def addpcipath(self, enable, channel, slot, function):
753                 """ Add a relative pci style path from our parent to this device """
754                 if (channel < 0):
755                         fatal("Invalid channel")
756                 if ((slot < 0) or (slot > 0x1f)):
757                         fatal("Invalid device id")
758                 if ((function < 0) or (function > 7)):
759                         fatal("Invalid function")
760                 self.path = "%s\n\t\t{ .channel = %d, .enable = %d, .path = {.type=DEVICE_PATH_PCI,.u={.pci={ .devfn = PCI_DEVFN(0x%x,%d) }}}}," % (self.path, channel, enable, slot, function)
761
762         def addpnppath(self, enable, channel, port, device):
763                 """ Add a relative path to a pnp device hanging off our parent """
764                 if (channel < 0):
765                         fatal("Invalid channel")
766                 if ((port < 0) or (port > 65536)):
767                         fatal("Invalid port")
768                 if ((device < 0) or (device > 0xff)):
769                         fatal("Invalid device")
770                 self.path = "%s\n\t\t{ .channel = %d, .enable = %d, .path={.type=DEVICE_PATH_PNP,.u={.pnp={ .port = 0x%x, .device = 0x%x }}}}," % (self.path, channel, enable, port, device)
771
772         def addi2cpath(self, enable, channel, device):
773                 """ Add a relative path to a i2c device hanging off our parent """
774                 if (channel < 0):
775                         fatal("Invalid channel")
776                 if ((device < 0) or (device > 0x7f)):
777                         fatal("Invalid device")
778                 self.path = "%s\n\t\t{ .channel = %d, .enable = %d, .path = {.type=DEVICE_PATH_I2C,.u={.i2c={ .device = 0x%x }}}}, " % (self.path, channel, enable, device)
779
780         def usesoption(self, name):
781                 """Declare option that can be used by this part"""
782                 global global_options
783                 o = getdict(global_options, name)
784                 if (o == 0):
785                         fatal("can't use undefined option %s" % name)
786                 o.setused()
787                 o1 = getdict(self.uses_options, name)
788                 if (o1):
789                         return
790                 setdict(self.uses_options, name, o)
791
792 # -----------------------------------------------------------------------------
793 #                    statements 
794 # -----------------------------------------------------------------------------
795
796 def getdict(dict, name):
797         if name not in dict.keys(): 
798                 debug.info(debug.dict, "Undefined: %s" % name)
799                 return 0
800         v = dict.get(name, 0)
801         debug.info(debug.dict, "getdict %s returning %s" % (name, v))
802         return v
803
804 def setdict(dict, name, value):
805         debug.info(debug.dict, "setdict sets %s to %s" % (name, value))
806         dict[name] = value
807
808 # options. 
809 # to create an option, it has to not exist. 
810 # When an option value is fetched, the fact that it was used is 
811 # remembered. 
812 # Legal things to do:
813 # set a default value, then set a real value before the option is used.
814 # set a value, try to set a default, default silently fails.
815 # Illegal:
816 # use the value, then try to set the value
817
818 def newoption(name):
819         global global_options, global_options_by_order
820         o = getdict(global_options, name)
821         if (o):
822                 print "option %s already defined" % name
823                 sys.exit(1)
824         o = option(name)
825         setdict(global_options, name, o)
826         global_options_by_order.append(name)
827
828 def getoption(name, image):
829         """option must be declared before being used in a part
830         if we're not processing a part, then we must
831         be at the top level where all options are available
832         global global_uses_options, global_option_values"""
833         curpart = partstack.tos()
834         if (curpart):
835                 o = getdict(curpart.uses_options, name)
836         elif (alloptions):
837                 o = getdict(global_options, name)
838         else:
839                 o = getdict(global_uses_options, name)
840         if (o == 0 or not o.defined):
841                 error("Option %s undefined (missing use command?)" % name)
842                 return
843         v = 0
844         if (image):
845                 v = o.getvalue(image, image.getvalues())
846         if (v == 0):
847                 v = o.getvalue(image, global_option_values)
848         return v.contents()
849
850 def setoption(name, value):
851         global loc, global_options, global_option_values, curimage
852         curpart = partstack.tos()
853         if (curpart and curpart.part != 'mainboard'):
854                 fatal("Options may only be set in top-level and mainboard configuration files")
855         o = getdict(global_uses_options, name)
856         if (o == 0):
857                 fatal("Attempt to set nonexistent option %s" % name)
858         v = option_value(value)
859         if (curimage):
860                 o.setvalue(v, curimage.getvalues(), loc)
861         else:
862                 o.setvalue(v, global_option_values, loc)
863
864 def setdefault(name, value):
865         global loc, global_options
866         o = getdict(global_options, name)
867         if (not o):
868                 return
869         if (o.default):
870                 print "setdefault: attempt to duplicate default for %s" % name
871                 return
872         v = option_value(value)
873         o.setdefault(v, loc)
874
875 def setnodefault(name):
876         global loc, global_options
877         o = getdict(global_options, name)
878         if (not o):
879                 return
880         if (o.default):
881                 print "setdefault: attempt to duplicate default for %s" % name
882                 return
883         o.setnodefault(loc)
884
885 def setcomment(name, value):
886         global loc, global_options
887         o = getdict(global_options, name)
888         if (not o):
889                 fatal("setcomment: %s not here" % name)
890         o.setcomment(value, loc)
891
892 def setexported(name):
893         global global_options
894         o = getdict(global_options, name)
895         if (not o):
896                 fatal("setexported: %s not here" % name)
897         o.setexported()
898
899 def setnoexport(name):
900         global global_options
901         o = getdict(global_options, name)
902         if (not o):
903                 fatal("setnoexport: %s not here" % name)
904         o.setnoexport()
905
906 def setexportable(name):
907         global global_options
908         o = getdict(global_options, name)
909         if (not o):
910                 fatal("setexportable: %s not here" % name)
911         o.setexportable()
912
913 def setformat(name, fmt):
914         global global_options
915         o = getdict(global_options, name)
916         if (not o):
917                 fatal("setformat: %s not here" % name)
918         o.setformat(fmt)
919
920 def getformated(name, image):
921         global global_options, global_option_values
922         o = getdict(global_options, name)
923         if (o == 0 or not o.defined):
924                 fatal( "Option %s undefined." % name)
925         v = 0
926         if (image):
927                 v = o.getvalue(image, image.getvalues())
928         if (v == 0):
929                 v = o.getvalue(image, global_option_values)
930         f = o.getformat()
931         return (f % v.contents())
932
933 def isexported(name):
934         global global_options
935         o = getdict(global_options, name)
936         if (o):
937                 return o.isexported()
938         return 0
939
940 #def isdefined(name, part):
941 #       global global_options
942 #       if (part):
943 #               o = getdict(part.uses_options, name)
944 #       else:
945 #               o = getdict(global_options, name)
946 #       if (o):
947 #               return o.isdefined()
948 #       return 0
949
950 def isset(name, part):
951         global global_uses_options
952         if (part):
953                 o = getdict(part.uses_options, name)
954         else:
955                 o = getdict(global_uses_options, name)
956         if (o):
957                 return o.isset()
958         return 0
959
960 #def isused(name, part):
961 #       global global_options
962 #       if (part):
963 #               o = getdict(part.uses_options, name)
964 #       else:
965 #               o = getdict(global_options, name)
966 #       if (o):
967 #               return o.isused()
968 #       return 0
969
970 def usesoption(name):
971         global global_options, global_uses_options
972         curpart = partstack.tos()
973         if (curpart):
974                 curpart.usesoption(name)
975                 return
976         o = getdict(global_options, name)
977         if (o == 0):
978                 fatal("Can't use undefined option %s" % name)
979         o.setused()
980         o1 = getdict(global_uses_options, name)
981         if (o1):
982                 return
983         setdict(global_uses_options, name, o)
984
985 def validdef(name, defval):
986         global global_options
987         o = getdict(global_options, name)
988         if (not o):
989                 fatal("validdef: %s not here" % name)
990         if ((defval & 1) != 1):
991             fatal("Must specify default value for option %s" % name)
992         if ((defval & 2) != 2):
993             fatal("Must specify export for option %s" % name)
994         if ((defval & 4) != 4):
995             fatal("Must specify comment for option %s" % name)
996
997 def loadoptions():
998         file = os.path.join('src', 'config', 'Options.lb')
999         optionsfile = os.path.join(treetop, file)
1000         fp = safe_open(optionsfile, 'r')
1001         loc.push(file)
1002         if (not parse('options', fp.read())):
1003                 fatal("Could not parse file")
1004         loc.pop()
1005
1006 def addinit(path):
1007         global curimage, dirstack
1008         if (path[0] == '/'):
1009                 curimage.setinitfile(treetop + '/src/' + path)
1010         else:
1011                 curimage.setinitfile(dirstack.tos() + '/' + path)
1012         print "Adding init file: %s" % path
1013
1014 def addconfig(path):
1015         global partstack
1016         curpart = partstack.tos()
1017         curpart.addconfig(path)
1018
1019 def addregister(field, value):
1020         global partstack
1021         curpart = partstack.tos()
1022         curpart.addregister(field, value)
1023
1024 def addcrt0include(path):
1025         """we do the crt0include as a dictionary, so that if needed we
1026         can trace who added what when. Also it makes the keys
1027         nice and unique."""
1028         global curimage
1029         curimage.addinitinclude(0, path)
1030
1031 def addinitinclude(str, path):
1032         global curimage
1033         curimage.addinitinclude(dequote(str), path)
1034
1035 def addldscript(path):
1036         global curimage, dirstack
1037         curdir = dirstack.tos()
1038         if (path[0] == '/'):
1039                 fullpath =  treetop + '/src/' + path
1040         else:
1041                 fullpath = curdir + '/' + path
1042         debug.info(debug.statement, "fullpath :%s: curdir :%s: path :%s:" % (fullpath, curdir, path))
1043         curimage.addldscript(fullpath)
1044
1045 def payload(path):
1046         global curimage
1047         curimage.setpayload(path)
1048         adduserdefine("PAYLOAD:=%s"%path)
1049 #       addrule('payload')
1050 #       adddep('payload', path)
1051 #       addaction('payload', 'cp $< $@')
1052
1053 def startromimage(name):
1054         global romimages, curimage, target_dir, target_name
1055         print "Configuring ROMIMAGE %s" % name
1056         o = getdict(romimages, name)
1057         if (o):
1058                 fatal("romimage %s previously defined" % name)
1059         curimage = romimage(name)
1060         curimage.settargetdir(os.path.join(target_dir, name))
1061         #o = partobj(curimage, target_dir, 0, 'board', target_name)
1062         #curimage.setroot(o)
1063         setdict(romimages, name, curimage)
1064
1065 def endromimage():
1066         global curimage
1067         print "End ROMIMAGE"
1068         curimage = 0
1069         #curpart = 0
1070
1071 def mainboard(path):
1072         full_path = os.path.join(treetop, 'src', 'mainboard', path)
1073         setoption('MAINBOARD', full_path)
1074         vendor = re.sub("/.*", "", path)
1075         part_number = re.sub("[^/]*/", "", path)
1076         setoption('MAINBOARD_VENDOR', vendor)
1077         setoption('MAINBOARD_PART_NUMBER', part_number)
1078         dodir('/config', 'Config.lb')
1079         part('mainboard', path, 'Config.lb', 0)
1080         curimage.setroot(partstack.tos())
1081         partpop()
1082
1083 def addbuildrom(filename, size, roms):
1084         global buildroms
1085         print "Build ROM size %d" % size
1086         b = buildrom(filename, size, roms)
1087         buildroms.append(b)
1088
1089 def addinitobject(object_name):
1090         global curimage
1091         curimage.addinitobjectrule(object_name)
1092
1093 def addobject(object_name):
1094         global curimage
1095         curimage.addobjectrule(object_name)
1096
1097 def adddriver(driver_name):
1098         global curimage
1099         curimage.adddriverrule(driver_name)
1100
1101 def target(name):
1102         global target_dir, target_name
1103         print "Configuring TARGET %s" % name
1104         target_name = name
1105         target_dir = os.path.join(os.path.dirname(loc.file()), name)
1106         if not os.path.isdir(target_dir):
1107                 print "Creating directory %s" % target_dir
1108                 os.makedirs(target_dir)
1109         print "Will place Makefile, crt0.S, etc. in %s" % target_dir
1110
1111
1112 def cpudir(path):
1113         global cpu_type
1114         if (cpu_type and (cpu_type != path)):
1115                 fatal("Two different CPU types: %s and %s" % (cpu_type, path))
1116         srcdir = "/cpu/%s" % path
1117         dodir(srcdir, "Config.lb")
1118         cpu_type = path
1119         
1120 def part(type, path, file, name):
1121         global curimage, dirstack, partstack
1122         partdir = os.path.join(type, path)
1123         srcdir = os.path.join(treetop, 'src')
1124         fulldir = os.path.join(srcdir, partdir)
1125         type_name = flatten_name(os.path.join(type, path))
1126         newpart = partobj(curimage, fulldir, partstack.tos(), type, \
1127                         type_name, name)
1128         print "Configuring PART %s, path %s" % (type, path)
1129         partstack.push(newpart)
1130         dirstack.push(fulldir)
1131         # special case for 'cpu' parts. 
1132         # we could add a new function too, but this is rather trivial.
1133         # if the part is a cpu, and we haven't seen it before, 
1134         # arrange to source the directory /cpu/'type'
1135         if (type == 'cpu'):
1136                 cpudir(path)
1137         else:
1138                 if (type == 'mainboard'):
1139                         doconfigfile(srcdir, partdir, file, 'mainboard_cfgfile')
1140                 else:
1141                         doconfigfile(srcdir, partdir, file, 'cfgfile')
1142
1143 def partpop():
1144         global dirstack, partstack
1145         curpart = partstack.pop()
1146         if (curpart == 0):
1147                 fatal("Trying to pop non-existent part")
1148         print "End PART %s" % curpart.part
1149         # Warn if options are used without being set in this part
1150         for i in curpart.uses_options.keys():
1151                 if (not isset(i, curpart)):
1152                         warning("Option %s using default value %s" % (i, getformated(i, curpart.image)))
1153         dirstack.pop()
1154
1155 def dodir(path, file):
1156         """dodir is like part but there is no new part"""
1157         global dirstack
1158         # if the first char is '/', it is relative to treetop, 
1159         # else relative to curdir
1160         # os.path.join screws up if the name starts with '/', sigh.
1161         print "Configuring DIR %s" % os.path.join(path, file)
1162         if (path[0] == '/'):
1163                 fullpath = os.path.join(treetop, 'src')
1164                 path = re.sub('^/*', '', path)
1165         else:
1166                 fullpath = dirstack.tos()
1167         debug.info(debug.statement, "DODIR: path %s, fullpath %s" % (path, fullpath))
1168         dirstack.push(os.path.join(fullpath, path))
1169         doconfigfile(fullpath, path, file, 'cfgfile')
1170         dirstack.pop()
1171
1172 def lookup(name):
1173         global curimage
1174         v = getoption(name, curimage)
1175         exitiferrors()
1176         return v
1177
1178 def addrule(id):
1179         global curimage
1180         curimage.addmakerule(id)
1181         
1182 def adduserdefine(str):
1183         global curimage
1184         curimage.adduserdefine(str)
1185
1186 def addaction(id, str):
1187         global curimage
1188         curimage.addmakeaction(id, str)
1189
1190 def adddep(id, str):
1191         global curimage
1192         curimage.addmakedepend(id, str)
1193
1194 def setarch(my_arch):
1195         """arch is 'different' ... darn it."""
1196         global curimage
1197         curimage.setarch(my_arch)
1198         setoption('ARCH', my_arch)
1199         part('arch', my_arch, 'Config.lb', 0)
1200
1201 def doconfigfile(path, confdir, file, rule):
1202         rname = os.path.join(confdir, file)
1203         loc.push(rname)
1204         fullpath = os.path.join(path, rname)
1205         fp = safe_open(fullpath, 'r')
1206         if (not parse(rule, fp.read())):
1207                 fatal("Could not parse file")
1208         exitiferrors()
1209         loc.pop()
1210
1211 #=============================================================================
1212 #               MISC FUNCTIONS
1213 #=============================================================================
1214 def ternary(val, yes, no):
1215         debug.info(debug.statement, "ternary %s" % expr)
1216         debug.info(debug.statement, "expr %s a %d yes %d no %d"% (expr, a, yes, no))
1217         if (val == 0):
1218                 debug.info(debug.statement, "Ternary returns %d" % yes)
1219                 return yes
1220         else:
1221                 debug.info(debug.statement, "Ternary returns %d" % no)
1222                 return no
1223
1224 def tohex(name):
1225         """atoi is in the python library, but not strtol? Weird!"""
1226         return eval('int(%s)' % name)
1227
1228 def IsInt( str ):
1229         """ Is the given string an integer?"""
1230         try:
1231                 num = long(str)
1232                 return 1
1233         except ValueError:
1234                 return 0
1235
1236 def dequote(str):
1237         a = re.sub("^\"", "", str)
1238         a = re.sub("\"$", "", a)
1239         # highly un-intuitive, need four \!
1240         a = re.sub("\\\\\"", "\"", a)
1241         return a
1242
1243 def flatten_name(str):
1244         a = re.sub("/", "_", str)
1245         return a
1246
1247 def topify(path):
1248         """If the first part of <path> matches treetop, replace 
1249         that part with $(TOP)"""
1250         if path[0:len(treetop)] == treetop:
1251                 path = path[len(treetop):len(path)]
1252                 if (path[0:1] == "/"):
1253                         path = path[1:len(path)]
1254                 path = "$(TOP)/" + path
1255         return path
1256
1257 %%
1258 # to make if work without 2 passses, we use an old hack from SIMD, the 
1259 # context bit. If the bit is 1, then ops get done, otherwise
1260 # ops don't get done. From the top level, context is always
1261 # 1. In an if, context depends on eval of the if condition
1262
1263 parser Config:
1264     ignore:                     r'\s+'
1265     ignore:                     "#.*?\r?\n"
1266
1267     # less general tokens should come first, otherwise they get matched
1268     # by the re's
1269     token ACTION:               'action'
1270     token ADDACTION:            'addaction'
1271     token ALWAYS:               'always'
1272     token ARCH:                 'arch'
1273     token BUILDROM:             'buildrom'
1274     token COMMENT:              'comment'
1275     token CONFIG:               'config'
1276     token CPU:                  'cpu'
1277     token DEFAULT:              'default'
1278     token DEFINE:               'define'
1279     token DEPENDS:              'depends'
1280     token DIR:                  'dir'
1281     token DRIVER:               'driver'
1282     token ELSE:                 'else'
1283     token END:                  'end'
1284     token EOF:                  '$'
1285     token EQ:                   '='
1286     token EXPORT:               'export'
1287     token FORMAT:               'format'
1288     token IF:                   'if'
1289     token INIT:                 'init'
1290     token INITOBJECT:           'initobject'
1291     token INITINCLUDE:          'initinclude'
1292     token LDSCRIPT:             'ldscript'
1293     token LOADOPTIONS:          'loadoptions'
1294     token MAINBOARD:            'mainboard'
1295     token MAINBOARDINIT:        'mainboardinit'
1296     token MAKEDEFINE:           'makedefine'
1297     token MAKERULE:             'makerule'
1298     token NEVER:                'never'
1299     token NONE:                 'none'
1300     token NORTHBRIDGE:          'northbridge'
1301     token OBJECT:               'object'
1302     token OPTION:               'option'
1303     token PAYLOAD:              'payload'
1304     token PMC:                  'pmc'
1305     token PRINT:                'print'
1306     token REGISTER:             'register'
1307     token ROMIMAGE:             'romimage'
1308     token SOUTHBRIDGE:          'southbridge'
1309     token SUPERIO:              'superio'
1310     token TARGET:               'target'
1311     token USED:                 'used'
1312     token USES:                 'uses'
1313     token NUM:                  '[0-9]+'
1314     token HEX_NUM:              '[0-9a-fA-F]+'
1315     token HEX_PREFIX:           '0x'
1316     # Why is path separate? Because paths to resources have to at least
1317     # have a slash, we thinks
1318     token PATH:                 r'[a-zA-Z0-9_.][a-zA-Z0-9/_.]+[a-zA-Z0-9_.]+'
1319     # Dir's on the other hand are abitrary
1320     # this may all be stupid.
1321     token DIRPATH:              r'[-a-zA-Z0-9_$()./]+'
1322     token ID:                   r'[a-zA-Z_.]+[a-zA-Z0-9_.]*'
1323     token DELEXPR:              r'{([^}]+|\\.)*}'
1324     token STR:                  r'"([^\\"]+|\\.)*"'
1325     token RAWTEXT:              r'.*'
1326     token ON:                   'on'
1327     token OFF:                  'off'
1328     token PCI:                  'pci'
1329     token PNP:                  'pnp'
1330     token I2C:                  'i2c'
1331
1332
1333     rule expr:          logical                 {{ l = logical }}
1334                         ( "&&" logical          {{ l = l and logical }}
1335                         | "||"  logical         {{ l = l or logical }}
1336                         )*                      {{ return l }}
1337
1338     rule logical:       factor                  {{ n = factor }}
1339                         ( "[+]" factor          {{ n = n+factor }}
1340                         | "-"  factor           {{ n = n-factor }}
1341                         )*                      {{ return n }}
1342
1343     rule factor:        term                    {{ v = term }}
1344                         ( "[*]" term            {{ v = v*term }}
1345                         | "/"  term             {{ v = v/term }}
1346                         | "<<"  term            {{ v = v << term }}
1347                         | ">=" term             {{ v = (v < term)}}
1348                         )*                      {{ return v }}
1349
1350     # A term is a number, variable, or an expression surrounded by parentheses
1351     rule term:          NUM                     {{ return long(NUM, 10) }}
1352                 |       HEX_PREFIX HEX_NUM      {{ return long(HEX_NUM, 16) }}
1353                 |       ID                      {{ return lookup(ID) }}
1354                 |       unop                    {{ return unop }}
1355                 |       "\\(" expr "\\)"        {{ return expr }}
1356
1357     rule unop:          "!" expr                {{ return not(expr) }}
1358
1359     rule partend<<C>>:  (stmt<<C>>)* END        {{ if (C): partpop()}}
1360
1361     # This is needed because the legacy cpu command could not distinguish
1362     # between cpu vendors. It should just be PATH, but getting this change
1363     # into the source tree will be tricky... 
1364     # DO NOT USE ID AS IT MAY GO AWAY IN THE FUTURE
1365     rule partid:        ID                      {{ return ID }}
1366                 |       PATH                    {{ return PATH }}
1367
1368     rule parttype:      NORTHBRIDGE             {{ return 'northbridge' }} 
1369                 |       SUPERIO                 {{ return 'superio' }}
1370                 |       PMC                     {{ return 'pmc' }}
1371                 |       SOUTHBRIDGE             {{ return 'southbridge' }}
1372                 |       CPU                     {{ return 'cpu' }}
1373
1374     rule partdef<<C>>:                          {{ name = 0 }}
1375                         parttype partid
1376                         [ STR                   {{ name = dequote(STR) }}
1377                         ]                       {{ if (C): part(parttype, partid, 'Config.lb', name) }}
1378                         partend<<C>>
1379
1380     rule arch<<C>>:     ARCH ID                 {{ if (C): setarch(ID) }}
1381                         partend<<C>>
1382     
1383     rule mainboardinit<<C>>:
1384                         MAINBOARDINIT DIRPATH   {{ if (C): addcrt0include(DIRPATH)}}
1385
1386     rule initinclude<<C>>: 
1387                         INITINCLUDE 
1388                         STR 
1389                         DIRPATH                 {{ if (C): addinitinclude(STR, DIRPATH)}}
1390
1391     rule initobject<<C>>:
1392                         INITOBJECT DIRPATH      {{ if (C): addinitobject(DIRPATH)}}
1393
1394     rule object<<C>>:   OBJECT DIRPATH          {{ if (C): addobject(DIRPATH)}}
1395
1396     rule driver<<C>>:   DRIVER DIRPATH          {{ if (C): adddriver(DIRPATH)}}
1397
1398     rule dir<<C>>:      DIR DIRPATH             {{ if (C): dodir(DIRPATH, 'Config.lb') }}
1399
1400     rule ldscript<<C>>: LDSCRIPT DIRPATH        {{ if (C): addldscript(DIRPATH) }}
1401
1402     rule iif<<C>>:      IF ID                   {{ c = lookup(ID) }}
1403                         (stmt<<C and c>>)* 
1404                         [ ELSE (stmt<<C and not c>>)* ]
1405                         END
1406
1407     rule depsacts<<ID, C>>:
1408                         ( DEPENDS STR           {{ if (C): adddep(ID, STR) }}
1409                         | ACTION STR            {{ if (C): addaction(ID, STR) }}
1410                         )*
1411
1412     rule makerule<<C>>: MAKERULE DIRPATH        {{ if (C): addrule(DIRPATH) }} 
1413                         depsacts<<DIRPATH, C>> 
1414                         END
1415
1416     rule makedefine<<C>>:
1417                         MAKEDEFINE RAWTEXT      {{ if (C): adduserdefine(RAWTEXT) }}
1418
1419     rule addaction<<C>>:
1420                         ADDACTION ID STR        {{ if (C): addaction(ID, STR) }}
1421
1422     rule init<<C>>:     INIT DIRPATH            {{ if (C): addinit(DIRPATH) }}
1423
1424     rule field:         STR                     {{ return STR }}
1425
1426     rule register<<C>>: REGISTER field '=' STR  {{ if (C): addregister(field, STR) }}
1427
1428     rule enable:                                {{ val = 1 }}
1429                         [ ( ON                  {{ val = 1 }}
1430                         | OFF                   {{ val = 0 }}
1431                         ) ]                     {{ return val }}
1432     
1433     rule pci<<C>>:      PCI HEX_NUM             {{ channel = int(HEX_NUM,16) }}
1434                         ':' HEX_NUM             {{ slot = int(HEX_NUM,16) }}
1435                         '.' HEX_NUM             {{ function = int(HEX_NUM, 16) }}
1436                         enable 
1437                                                 {{ if (C): partstack.tos().addpcipath(enable, channel, slot, function) }}
1438
1439     rule pnp<<C>>:      PNP HEX_NUM             {{ channel = int(HEX_NUM,16) }}
1440                         ':' HEX_NUM             {{ port = int(HEX_NUM,16) }}
1441                         '.' HEX_NUM             {{ device = int(HEX_NUM, 16) }}
1442                         enable
1443                                                 {{ if (C): partstack.tos().addpnppath(enable, channel, port, device) }}
1444
1445     rule i2c<<C>>:      I2C HEX_NUM             {{ channel = int(HEX_NUM, 16) }}
1446                         ':' HEX_NUM             {{ device = int(HEX_NUM, 16) }}
1447                         enable
1448                                                 {{ if (C): partstatck.tos().addi2cpath(enable, channel, device) }}
1449                         
1450     rule prtval:        expr                    {{ return str(expr) }}
1451                 |       STR                     {{ return STR }}
1452
1453     rule prtlist:       prtval                  {{ el = "%(" + prtval }}
1454                         ( "," prtval            {{ el = el + "," + prtval }}
1455                         )*                      {{ return el + ")" }}   
1456
1457     rule prtstmt<<C>>:  PRINT STR               {{ val = STR }}
1458                         [ "," prtlist           {{ val = val + prtlist }}
1459                         ]                       {{ if (C): print eval(val) }}
1460
1461     rule config<<C>>:   CONFIG PATH             {{ if (C): addconfig(PATH) }}
1462
1463     rule stmt<<C>>:     arch<<C>>               {{ return arch}}
1464                 |       addaction<<C>>          {{ return addaction }}
1465                 |       config<<C>>             {{ return config}}
1466                 |       dir<<C>>                {{ return dir}}
1467                 |       driver<<C>>             {{ return driver }}
1468                 |       iif<<C>>                {{ return iif }}
1469                 |       init<<C>>               {{ return init }}
1470                 |       initinclude<<C>>        {{ return initinclude }}
1471                 |       initobject<<C>>         {{ return initobject }}
1472                 |       ldscript<<C>>           {{ return ldscript}}
1473                 |       mainboardinit<<C>>      {{ return mainboardinit }}
1474                 |       makedefine<<C>>         {{ return makedefine }}
1475                 |       makerule<<C>>           {{ return makerule }}
1476                 |       object<<C>>             {{ return object }}
1477                 |       option<<C>>             {{ return option }}
1478                 |       partdef<<C>>            {{ return partdef }}
1479                 |       prtstmt<<C>>            {{ return prtstmt }}
1480                 |       register<<C>>           {{ return register }}
1481                 |       pci<<C>>                {{ return pci }}
1482                 |       pnp<<C>>                {{ return pnp }}
1483
1484     # ENTRY for parsing Config.lb file
1485     rule cfgfile:       (uses<<1>>)* 
1486                         (stmt<<1>>)*
1487                         EOF                     {{ return 1 }}
1488     #mainboard config files are special, in that they can also have
1489     # default values.
1490     rule mainboard_cfgfile:     (uses<<1>>)* 
1491                             (defstmts<<1>>)*
1492                         (stmt<<1>>)*
1493                         EOF                     {{ return 1 }}
1494
1495     rule usesid<<C>>:   ID                      {{ if (C): usesoption(ID) }}
1496
1497     rule uses<<C>>:     USES (usesid<<C>>)+
1498
1499     rule value:         STR                     {{ return dequote(STR) }} 
1500                 |       expr                    {{ return expr }}
1501                 |       DELEXPR                 {{ return DELEXPR }}
1502
1503     rule option<<C>>:   OPTION ID EQ value      {{ if (C): setoption(ID, value) }}
1504
1505     rule opif<<C>>:     IF ID                   {{ c = lookup(ID) }}
1506                         (opstmt<<C and c>>)* 
1507                         [ ELSE (opstmt<<C and not c>>)* ] 
1508                         END
1509
1510     rule opstmt<<C>>:   option<<C>>
1511                 |       opif<<C>>
1512                 |       prtstmt<<C>>
1513
1514     rule payload<<C>>:  PAYLOAD DIRPATH         {{ if (C): payload(DIRPATH) }}
1515
1516     rule mainboard<<C>>:
1517                         MAINBOARD PATH          {{ if (C): mainboard(PATH) }}
1518
1519     rule romif<<C>>:    IF ID                   {{ c = lookup(ID) }}
1520                         (romstmt<<C and c>>)* 
1521                         [ ELSE (romstmt<<C and not c>>)* ]
1522                         END
1523
1524     rule romstmt<<C>>:  romif<<C>>
1525                 |       option<<C>>
1526                 |       mainboard<<C>>
1527                 |       payload<<C>>
1528
1529     rule romimage:      ROMIMAGE STR            {{ startromimage(dequote(STR)) }}
1530                         (romstmt<<1>>)*
1531                         END                     {{ endromimage() }}
1532
1533     rule roms:          STR                     {{ s = '(' + STR }}
1534                         ( STR                   {{ s = s + "," + STR }}
1535                         )*                      {{ return eval(s + ')') }}
1536
1537     rule buildrom:      BUILDROM DIRPATH expr roms      {{ addbuildrom(DIRPATH, expr, roms) }}
1538
1539     rule romstmts:      romimage 
1540                 |       buildrom
1541                 |       opstmt<<1>>
1542
1543     # ENTRY for parsing root part
1544     rule board:         LOADOPTIONS             {{ loadoptions() }}
1545                         TARGET DIRPATH          {{ target(DIRPATH) }}
1546                         (uses<<1>>)*
1547                         (romstmts)*             
1548                         EOF                     {{ return 1 }}
1549
1550     # ENTRY for parsing a delayed value
1551     rule delexpr:       "{" expr "}" EOF        {{ return expr }}
1552
1553     rule defstmts<<ID>>:                        {{ d = 0 }}
1554                         ( DEFAULT
1555                           ( value               {{ setdefault(ID, value) }}
1556                           | NONE                {{ setnodefault(ID) }}
1557                           )                     {{ d = d | 1 }}
1558                         | FORMAT STR            {{ setformat(ID, dequote(STR)) }}
1559                         | EXPORT 
1560                           ( ALWAYS              {{ setexported(ID) }}
1561                           | USED                {{ setexportable(ID) }}
1562                           | NEVER               {{ setnoexport(ID) }}
1563                           )                     {{ d = d | 2 }}
1564                         | COMMENT STR           {{ setcomment(ID, dequote(STR)); d = d | 4 }}
1565                         )+                      {{ return d }}
1566                 
1567     rule define:        DEFINE ID               {{ newoption(ID) }}
1568                         defstmts<<ID>> END      {{ validdef(ID, defstmts) }}
1569
1570     # ENTRY for parsing Options.lb file
1571     rule options:       (define)* EOF           {{ return 1 }}
1572 %%
1573
1574 #=============================================================================
1575 #               FILE OUTPUT 
1576 #=============================================================================
1577 def writemakefileheader(file, fname):
1578         file.write("# File: %s\n" % fname)
1579         file.write("# This file was generated by '%s %s %s'\n\n"
1580                 % (sys.argv[0], sys.argv[1], sys.argv[2]))
1581
1582 def writemakefilesettings(path):
1583         global treetop, target_dir
1584         # Write Makefile.settings to seperate the settings
1585         # from the actual makefile creation
1586         # In practice you need to rerun NLBConfig.py to change
1587         # these but in theory you shouldn't need to.
1588
1589         filename = os.path.join(path, "Makefile.settings")
1590         print "Creating", filename
1591         file = safe_open(filename, 'w+')
1592         writemakefileheader(file, filename)
1593         file.write("TOP:=%s\n" % (treetop))
1594         file.write("TARGET_DIR:=%s\n" % target_dir)
1595 #       for i in global_options_by_order:
1596 #               if (isexported(i, 0)):
1597 #                       file.write("export %s:=%s\n" % (i, getformated(i, 0)))
1598 #       file.write("export VARIABLES := ")
1599 #       for i in global_options.keys():
1600 #               if (isexported(i, 0)):
1601 #                       file.write("%s " % i)
1602         file.write("\n")
1603         file.close()
1604
1605 def writeimagesettings(image):
1606         global treetop
1607         global global_options_by_order
1608         # Write Makefile.settings to seperate the settings
1609         # from the actual makefile creation
1610         # In practice you need to rerun NLBConfig.py to change
1611         # these but in theory you shouldn't need to.
1612
1613         filename = os.path.join(image.gettargetdir(), "Makefile.settings")
1614         print "Creating", filename
1615         file = safe_open(filename, 'w+')
1616         writemakefileheader(file, filename)
1617         file.write("TOP:=%s\n" % (treetop))
1618         file.write("TARGET_DIR:=%s\n" % (image.gettargetdir()))
1619         for i in global_options_by_order:
1620                 if (isexported(i)):
1621                         file.write("export %s:=%s\n" % (i, getformated(i, image)))
1622         file.write("export VARIABLES := ")
1623         for i in global_options_by_order:
1624                 if (isexported(i)):
1625                         file.write("%s " % i)
1626         file.write("\n")
1627         file.close()
1628
1629 # write the romimage makefile
1630 # let's try the Makefile
1631 # first, dump all the -D stuff
1632
1633 def writeimagemakefile(image):
1634         makefilepath = os.path.join(image.gettargetdir(), "Makefile")
1635         print "Creating", makefilepath
1636         file = safe_open(makefilepath, 'w+')
1637         writemakefileheader(file, makefilepath)
1638
1639         #file.write("include cpuflags\n")
1640         # Putting "include cpuflags" in the Makefile has the problem that the
1641         # cpuflags file would be generated _after_ we want to include it.
1642         # Instead, let make do the work of computing CPUFLAGS:
1643         file.write("# Get the value of TOP, VARIABLES, and several other variables.\n")
1644         file.write("include Makefile.settings\n\n")
1645         file.write("# Function to create an item like -Di586 or -DCONFIG_MAX_CPUS='1' or -Ui686\n")
1646         file.write("D_item = $(if $(subst undefined,,$(origin $1)),-D$1$(if $($1),='$($1)',),-U$1)\n\n")
1647         file.write("# Compute the value of CPUFLAGS here during make's first pass.\n")
1648         file.write("CPUFLAGS := $(foreach _var_,$(VARIABLES),$(call D_item,$(_var_)))\n\n")
1649
1650         for i in image.getuserdefines():
1651                 file.write("%s\n" %i)
1652         file.write("\n")
1653
1654         # main rule
1655         file.write("all: linuxbios.rom")
1656         # print out all the object dependencies
1657         file.write("\n# object dependencies (objectrules:)\n")
1658         file.write("INIT-OBJECTS :=\n")
1659         file.write("OBJECTS :=\n")
1660         file.write("DRIVER :=\n")
1661         file.write("\nSOURCES :=\n")
1662         for irule, init in image.getinitobjectrules().items():
1663                 i_name = init[0]
1664                 i_source = init[1]
1665                 file.write("INIT-OBJECTS += %s\n" % (i_name))
1666                 file.write("SOURCES += %s\n" % (i_source))
1667
1668         for objrule, obj in image.getobjectrules().items():
1669                 obj_name = obj[0]
1670                 obj_source = obj[1]
1671                 file.write("OBJECTS += %s\n" % (obj_name))
1672                 file.write("SOURCES += %s\n" % (obj_source))
1673
1674         # for chip_target.c
1675         file.write("OBJECTS += static.o\n")
1676         file.write("SOURCES += static.c\n")
1677
1678         for driverrule, driver in image.getdriverrules().items():
1679                 obj_name = driver[0]
1680                 obj_source = driver[1]
1681                 file.write("DRIVER += %s\n" % (obj_name))
1682                 file.write("SOURCES += %s\n" % (obj_source))
1683
1684         # Print out all ldscript.ld dependencies.
1685         file.write("\n# ldscript.ld dependencies:\n")
1686         file.write("LDSUBSCRIPTS-1 := \n" )
1687         for script in image.getldscripts():
1688                 file.write("LDSUBSCRIPTS-1 += %s\n" % topify(script))
1689
1690         # Print out the dependencies for crt0_includes.h
1691         file.write("\n# Dependencies for crt0_includes.h\n")
1692         file.write("CRT0_INCLUDES:=\n")
1693         for inc in image.getinitincludes():
1694                 if (local_path.match(inc)):
1695                         file.write("CRT0_INCLUDES += %s\n" % inc)
1696                 else:
1697                         file.write("CRT0_INCLUDES += $(TOP)/src/%s\n" % inc)
1698
1699         # Print out the user defines.
1700         file.write("\n# userdefines:\n")
1701         #for udef in image.userdefines:
1702                 #file.write("%s\n" % udef)
1703                 
1704         # Print out the base rules.
1705         # Need to have a rule that counts on 'all'.
1706         file.write("\n# mainrulelist:")
1707         #file.write("\nmainrule: %s\n" % image.mainrulelist)
1708
1709         # Print out any user rules.
1710         file.write("\n# From makerule or docipl commands:\n")
1711         # Old way (hash order): for target in makebaserules.keys():
1712         # New way (config file order):
1713         #for target in image.makerule_targets:
1714                 #image.makebaserules[target].write(file)
1715
1716         file.write("\n# objectrules:\n")
1717         for objrule, obj in image.getobjectrules().items():
1718                 source = topify(obj[1])
1719                 type = obj[2]
1720                 if (type  == 'S'):
1721                         # for .S, .o depends on .s
1722                         file.write("%s: %s.s\n" % (obj[0], obj[3]))
1723                         file.write("\t@echo $(CC) ... -o $@ $<\n")
1724                         file.write("\t$(CC) -c $(CPU_OPT) -o $@ $<\n")
1725                         # and .s depends on .S
1726                         file.write("%s.s: %s\n" % (obj[3], source))
1727                         file.write("\t@echo $(CPP) ... $< > $@\n")
1728                         # Note: next 2 lines are ONE output line!
1729                         file.write("\t$(CPP) $(CPPFLAGS) $< ")
1730                         file.write(">$@.new && mv $@.new $@\n")
1731                 else:
1732                         file.write("%s: %s\n" % (obj[0], source))
1733                         file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
1734                 #file.write("%s\n" % objrule[2])
1735
1736         for driverrule, driver in image.getdriverrules().items():
1737                 source = topify(driver[1])
1738                 file.write("%s: %s\n" % (driver[0], source))
1739                 file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
1740                 #file.write("%s\n" % objrule[2])
1741
1742         # special rule for chip_target.c
1743         file.write("static.o: static.c\n")
1744         file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
1745
1746         # Print out the rules that will make cause the files
1747         # generated by NLBConfig.py to be remade if any dependencies change.
1748
1749         file.write("\n# Remember the automatically generated files\n")
1750         file.write("GENERATED:=\n")
1751         for genfile in ['Makefile',
1752                         'nsuperio.c',
1753                         'static.c',
1754                         'LinuxBIOSDoc.config' ]:
1755                 file.write("GENERATED += %s\n" % genfile)
1756         file.write("GENERATED += %s\n" % image.getincludefilename())
1757
1758         #file.write("\n# Remake Makefile (and the other files generated by\n")
1759         #file.write("# NLBConfig.py) if any config dependencies change.\n")
1760
1761         #for cfile in image.config_file_list:
1762         #       file.write("$(GENERATED): %s\n" % topify(cfile))
1763
1764         #for depfile in [ '%s' % top_config_file,    # This a duplicate, remove?
1765         #               '$(TOP)/util/config/NLBConfig.py',
1766         #               '$(TOP)/src/arch/$(ARCH)/config/make.base' ]:
1767         #       file.write("$(GENERATED): %s\n" % depfile)
1768
1769         #file.write("$(GENERATED):\n")
1770         #file.write("\tpython $(TOP)/util/config/NLBConfig.py %s $(TOP)\n"
1771         #               % top_config_file)
1772
1773         #keys = image.getroot().uses_options.keys()
1774         keys = global_options_by_order
1775         keys.sort()
1776         file.write("\necho:\n")
1777         for key in keys:
1778                  file.write("\t@echo %s='$(%s)'\n"% (key,key))
1779
1780         for i, m in image.getmakerules().items():
1781                 file.write("%s: " %i)
1782                 for i in m.dependency:
1783                         file.write("%s " % i)
1784                 file.write("\n")
1785                 for i in m.actions:
1786                         file.write("\t%s\n" % i)
1787         file.close()
1788
1789 #
1790 def writemakefile(path):
1791         makefilepath = os.path.join(path, "Makefile")
1792         print "Creating", makefilepath
1793         file = safe_open(makefilepath, 'w+')
1794         writemakefileheader(file, makefilepath)
1795
1796         # main rule
1797         file.write("all: ")
1798         for i in romimages.keys():
1799                 file.write("%s-rom " % i)
1800         file.write("buildroms\n\n")
1801         for i, o in romimages.items():
1802                 file.write("%s-rom:\n" % o.getname())
1803                 file.write("\tif (cd %s; \\\n" % o.getname())
1804                 file.write("\t\tmake linuxbios.rom)\\\n");
1805                 file.write("\tthen true; else exit 1; fi;\n\n")
1806         file.write("clean: ")
1807         for i in romimages.keys():
1808                 file.write("%s-clean " % i)
1809         file.write("\n\n")
1810         for i, o in romimages.items():
1811                 file.write("%s-clean:\n" % o.getname())
1812                 file.write("\t(cd %s; make clean)\n" % o.getname())
1813         
1814         file.write("\nbuildroms:\n")
1815         for i in range(len(buildroms)):
1816                 file.write("\tcat ");
1817                 for j in range(len(buildroms[i])):
1818                         file.write("%s/linuxbios.rom " % buildroms[i][j] )
1819                 file.write("> %s\n" % buildroms[i].name);
1820         file.write("\n\n")
1821         
1822         file.close()
1823
1824 def writeinitincludes(image):
1825         global include_pattern
1826         filepath = os.path.join(image.gettargetdir(), image.getincludefilename())
1827         print "Creating", filepath
1828         outfile = safe_open(filepath, 'w+')
1829         if (image.newformat()):
1830                 infile = safe_open(image.getinitfile(), 'r')
1831
1832                 line = infile.readline()
1833                 while (line):
1834                         p = include_pattern.match(line)
1835                         if (p):
1836                                 for i in image.getinitincludes():
1837                                         inc = image.getinitinclude(i)
1838                                         if (inc.getstring() == p.group(1)):
1839                                                 outfile.write("#include \"%s\"\n" % inc.getpath())
1840                         else:
1841                                 outfile.write(line);
1842                         line = infile.readline()
1843
1844                 infile.close()
1845         else:
1846                 for i in image.getinitincludes():
1847                         outfile.write("#include <%s>\n" % i)
1848         outfile.close()
1849
1850 def writeldoptions(image):
1851         # Write Makefile.settings to seperate the settings
1852         # from the actual makefile creation
1853         # In practice you need to rerun NLBConfig.py to change
1854         # these but in theory you shouldn't need to.
1855
1856         filename = os.path.join(image.gettargetdir(), "ldoptions")
1857         print "Creating", filename
1858         file = safe_open(filename, 'w+')
1859         for i in global_options.keys():
1860                 if (isexported(i) and IsInt(getoption(i, image))):
1861                         file.write("%s = %s;\n" % (i, getformated(i, image)))
1862         file.close()
1863
1864 def dumptree(part, lvl):
1865         debug.info(debug.dumptree, "DUMPTREE ME is")
1866         part.dumpme(lvl)
1867         # dump the siblings -- actually are there any? not sure
1868         # siblings are:
1869         debug.info(debug.dumptree, "DUMPTREE SIBLINGS are")
1870         kid = part.siblings
1871         while (kid):
1872                 kid.dumpme(lvl)
1873                 kid = kid.siblings
1874         # dump the kids
1875         debug.info(debug.dumptree, "DUMPTREE KIDS are")
1876         #for kid in part.children:
1877         if (part.children):
1878                 dumptree(part.children, lvl+1)
1879         debug.info(debug.dumptree, "DONE DUMPTREE")
1880
1881 def writecode(image):
1882         filename = os.path.join(img_dir, "static.c")
1883         print "Creating", filename
1884         file = safe_open(filename, 'w+')
1885         file.write("#include <device/chip.h>\n")
1886         file.write("#include <device/pci.h>\n")
1887         for path in image.getconfigincludes().values():
1888                 file.write("#include \"%s\"\n" % path)
1889         gencode(image.getroot(), file, 0)
1890         gencode(image.getroot(), file, 1)
1891         file.close()
1892
1893 def gencode(part, file, pass_num):
1894         debug.info(debug.gencode, "GENCODE ME is")
1895         part.gencode(file, pass_num)
1896         # dump the siblings -- actually are there any? not sure
1897         debug.info(debug.gencode, "GENCODE SIBLINGS are")
1898         kid = part.siblings
1899         while (kid):
1900                 kid.gencode(file, pass_num)
1901                 kid = kid.siblings
1902         # now dump the children 
1903         debug.info(debug.gencode, "GENCODE KIDS are")
1904         if (part.children):
1905                 gencode(part.children, file, pass_num)
1906         kid = part.siblings
1907         while (kid):
1908                 if (kid.children):
1909                         gencode(kid.children, file, pass_num)
1910                 kid = kid.siblings
1911         debug.info(debug.gencode, "DONE GENCODE")
1912
1913 def verifyparse(image):
1914         """Add any run-time checks to verify that parsing the configuration
1915         was successful"""
1916         if (image.newformat() and image.getinitfile() == ''):
1917                 fatal("An init file must be specified")
1918
1919 #=============================================================================
1920 #               MAIN PROGRAM
1921 #=============================================================================
1922 if __name__=='__main__':
1923         from sys import argv
1924         if (len(argv) < 3):
1925                 print 'Args: <file> <path to linuxbios>'
1926                 sys.exit(1)
1927
1928         top_config_file = os.path.abspath(sys.argv[1])
1929
1930         treetop = os.path.abspath(sys.argv[2])
1931
1932         # Now read in the customizing script...
1933         loc.push(argv[1])
1934         fp = safe_open(argv[1], 'r')
1935         if (not parse('board', fp.read())):
1936                 fatal("Could not parse file")
1937         loc.pop()
1938
1939         for image_name, image in romimages.items():
1940                 verifyparse(image)
1941
1942         # no longer need to check if an options has been used
1943         alloptions = 1
1944
1945         for image_name, image in romimages.items():
1946                 if (debug.level(debug.dumptree)):
1947                         debug.info(debug.dumptree, "DEVICE TREE:")
1948                         dumptree(image.getroot(), 0)
1949
1950                 img_dir = image.gettargetdir()
1951                 if not os.path.isdir(img_dir):
1952                         print "Creating directory %s" % img_dir
1953                         os.makedirs(img_dir)
1954
1955                 if (debug.level(debug.dump)):
1956                         for i in image.getinitincludes():
1957                                 debug.info(debug.dump, "crt0include file %s" % i)
1958                         for i in image.getdriverrules().keys():
1959                                 debug.info(debug.dump, "driver file %s" % i)
1960                         for i in image.getldscripts():
1961                                 debug.info(debug.dump, "ldscript file %s" % i)
1962                         for i, m in image.getmakerules().items():
1963                                 debug.info(debug.dump, " makerule %s dep %s act %s" % (i, m.dependency, m.actions))
1964
1965                 writecode(image)
1966                 writeimagesettings(image)
1967                 writeinitincludes(image)
1968                 writeimagemakefile(image)
1969                 writeldoptions(image)
1970
1971         writemakefilesettings(target_dir)
1972         writemakefile(target_dir)
1973
1974         sys.exit(0)