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