ieee1275: split up grub_machine_get_bootlocation
[grub.git] / gentpl.py
index f0f4493..da67965 100644 (file)
--- a/gentpl.py
+++ b/gentpl.py
@@ -15,6 +15,8 @@
 #  You should have received a copy of the GNU General Public License
 #  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 
+from __future__ import print_function
+
 __metaclass__ = type
 
 from optparse import OptionParser
@@ -29,7 +31,8 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot",
                    "i386_xen", "x86_64_xen",
                    "mips_loongson", "sparc64_ieee1275",
                    "powerpc_ieee1275", "mips_arc", "ia64_efi",
-                   "mips_qemu_mips", "arm_uboot", "arm_efi" ]
+                   "mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi",
+                   "arm_coreboot"]
 
 GROUPS = {}
 
@@ -42,13 +45,15 @@ GROUPS["x86"]      = GROUPS["i386"] + GROUPS["x86_64"]
 GROUPS["mips"]     = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ]
 GROUPS["sparc64"]  = [ "sparc64_ieee1275" ]
 GROUPS["powerpc"]  = [ "powerpc_ieee1275" ]
-GROUPS["arm"]      = [ "arm_uboot", "arm_efi" ]
+GROUPS["arm"]      = [ "arm_uboot", "arm_efi", "arm_coreboot" ]
+GROUPS["arm64"]    = [ "arm64_efi" ]
 
 # Groups based on firmware
-GROUPS["efi"]  = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi" ]
+GROUPS["efi"]  = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi" ]
 GROUPS["ieee1275"]   = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ]
 GROUPS["uboot"] = [ "arm_uboot" ]
 GROUPS["xen"]  = [ "i386_xen", "x86_64_xen" ]
+GROUPS["coreboot"]  = [ "i386_coreboot", "arm_coreboot" ]
 
 # emu is a special case so many core functionality isn't needed on this platform
 GROUPS["noemu"]   = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu")
@@ -58,10 +63,10 @@ GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips",
                                      "sparc64_ieee1275", "powerpc_ieee1275"]
 GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi");
 GROUPS["pci"]      = GROUPS["x86"] + ["mips_loongson"]
-GROUPS["usb"]      = GROUPS["pci"]
+GROUPS["usb"]      = GROUPS["pci"] + ["arm_coreboot"]
 
 # If gfxterm is main output console integrate it into kernel
-GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot" ]
+GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot", "arm_coreboot" ]
 GROUPS["videomodules"]   = GRUB_PLATFORMS[:];
 for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i)
 
@@ -71,9 +76,15 @@ GROUPS["terminfomodule"]   = GRUB_PLATFORMS[:];
 for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i)
 
 # Flattened Device Trees (FDT)
-GROUPS["fdt"] = [ "arm_uboot", "arm_efi" ]
+GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi" ]
+
+# Needs software helpers for division
+# Must match GRUB_DIVISION_IN_SOFTWARE in misc.h
+GROUPS["softdiv"] = GROUPS["arm"] + ["ia64_efi"]
+GROUPS["no_softdiv"]   = GRUB_PLATFORMS[:]
+for i in GROUPS["softdiv"]: GROUPS["no_softdiv"].remove(i)
 
-# Miscelaneous groups schedulded to disappear in future
+# Miscellaneous groups scheduled to disappear in future
 GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"]
 GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc")
 
@@ -106,9 +117,11 @@ for platform in GRUB_PLATFORMS:
 #
 
 # We support a subset of the AutoGen definitions file syntax.  Specifically,
-# compound names are disallowed; C-style comments and preprocessing
-# directives are disallowed; and shell-generated strings, Scheme-generated
-# strings, and here strings are disallowed.
+# compound names are disallowed; some preprocessing directives are
+# disallowed (though #if/#endif are allowed; note that, like AutoGen, #if
+# skips everything to the next #endif regardless of the value of the
+# conditional); and shell-generated strings, Scheme-generated strings, and
+# here strings are disallowed.
 
 class AutogenToken:
     (autogen, definitions, eof, var_name, other_name, string, number,
@@ -119,14 +132,15 @@ class AutogenState:
      need_idx, need_rbracket, indx_name, have_value, done) = range(12)
 
 class AutogenParseError(Exception):
-    def __init__(self, message, line):
+    def __init__(self, message, path, line):
         super(AutogenParseError, self).__init__(message)
+        self.path = path
         self.line = line
 
     def __str__(self):
         return (
             super(AutogenParseError, self).__str__() +
-            " at line %d" % self.line)
+            " at file %s line %d" % (self.path, self.line))
 
 class AutogenDefinition(list):
     def __getitem__(self, key):
@@ -161,6 +175,7 @@ class AutogenParser:
         self.def_stack = [("", self.definitions)]
         self.curdef = None
         self.new_name = None
+        self.cur_path = None
         self.cur_line = 0
 
     @staticmethod
@@ -172,6 +187,9 @@ class AutogenParser:
     def is_value_name_char(c):
         return c in ":^-_" or c.isalnum()
 
+    def error(self, message):
+        raise AutogenParseError(message, self.cur_file, self.cur_line)
+
     def read_tokens(self, f):
         data = f.read()
         end = len(data)
@@ -184,7 +202,27 @@ class AutogenParser:
             if offset >= end:
                 break
             c = data[offset]
-            if c == "{":
+            if c == "#":
+                offset += 1
+                try:
+                    end_directive = data.index("\n", offset)
+                    directive = data[offset:end_directive]
+                    offset = end_directive
+                except ValueError:
+                    directive = data[offset:]
+                    offset = end
+                name, value = directive.split(None, 1)
+                if name == "if":
+                    try:
+                        end_if = data.index("\n#endif", offset)
+                        new_offset = end_if + len("\n#endif")
+                        self.cur_line += data[offset:new_offset].count("\n")
+                        offset = new_offset
+                    except ValueError:
+                        self.error("#if without matching #endif")
+                else:
+                    self.error("Unhandled directive '#%s'" % name)
+            elif c == "{":
                 yield AutogenToken.lbrace, c
                 offset += 1
             elif c == "=":
@@ -210,15 +248,13 @@ class AutogenParser:
                 while True:
                     offset += 1
                     if offset >= end:
-                        raise AutogenParseError(
-                            "EOF in quoted string", self.cur_line)
+                        self.error("EOF in quoted string")
                     if data[offset] == "\n":
                         self.cur_line += 1
                     if data[offset] == "\\":
                         offset += 1
                         if offset >= end:
-                            raise AutogenParseError(
-                                "EOF in quoted string", self.cur_line)
+                            self.error("EOF in quoted string")
                         if data[offset] == "\n":
                             self.cur_line += 1
                         # Proper escaping unimplemented; this can be filled
@@ -231,6 +267,22 @@ class AutogenParser:
                     else:
                         s.append(data[offset])
                 yield AutogenToken.string, "".join(s)
+            elif c == "/":
+                offset += 1
+                if data[offset] == "*":
+                    offset += 1
+                    try:
+                        end_comment = data.index("*/", offset)
+                        new_offset = end_comment + len("*/")
+                        self.cur_line += data[offset:new_offset].count("\n")
+                        offset = new_offset
+                    except ValueError:
+                        self.error("/* without matching */")
+                elif data[offset] == "/":
+                    try:
+                        offset = data.index("\n", offset)
+                    except ValueError:
+                        pass
             elif (c.isdigit() or
                   (c == "-" and offset < end - 1 and
                    data[offset + 1].isdigit())):
@@ -260,21 +312,19 @@ class AutogenParser:
                         yield AutogenToken.var_name, s
                     offset = end_name
             else:
-                raise AutogenParseError(
-                    "Invalid input character '%s'" % c, self.cur_line)
+                self.error("Invalid input character '%s'" % c)
         yield AutogenToken.eof, None
 
     def do_need_name_end(self, token):
         if len(self.def_stack) > 1:
-            raise AutogenParseError(
-                "Definition blocks were left open", self.cur_line)
+            self.error("Definition blocks were left open")
 
     def do_need_name_var_name(self, token):
         self.new_name = token
 
     def do_end_block(self, token):
         if len(self.def_stack) <= 1:
-            raise AutogenParseError("Too many close braces", self.cur_line)
+            self.error("Too many close braces")
         new_name, parent_def = self.def_stack.pop()
         parent_def.append((new_name, self.curdef))
         self.curdef = parent_def
@@ -292,7 +342,7 @@ class AutogenParser:
     def do_indexed_name(self, token):
         self.new_name = token
 
-    def read_definitions(self, f):
+    def read_definitions_file(self, f):
         self.curdef = self.definitions
         self.cur_line = 0
         state = AutogenState.init
@@ -367,12 +417,17 @@ class AutogenParser:
                 if handler is not None:
                     handler(token)
             else:
-                raise AutogenParseError(
+                self.error(
                     "Parse error in state %s: unexpected token '%s'" % (
-                        state, token), self.cur_line)
+                        state, token))
             if state == AutogenState.done:
                 break
 
+    def read_definitions(self, path):
+        self.cur_file = path
+        with open(path) as f:
+            self.read_definitions_file(f)
+
 defparser = AutogenParser()
 
 #
@@ -389,7 +444,7 @@ def output(s, section=''):
 
 def write_output(section=''):
     for s in outputs.get(section, []):
-        print s,
+        print(s, end='')
 
 #
 # Global variables
@@ -553,7 +608,7 @@ def foreach_enabled_platform(defn, closure):
 #    enable = emu;
 #    enable = i386;
 #    enable = mips_loongson;
-#    emu_condition = COND_GRUB_EMU_USB;
+#    emu_condition = COND_GRUB_EMU_SDL;
 #  };
 #
 def under_platform_specific_conditionals(defn, platform, closure):
@@ -594,6 +649,28 @@ def first_time(defn, snippet):
         return snippet
     return ''
 
+def is_platform_independent(defn):
+    if 'enable' in defn:
+        return False
+    for suffix in [ "", "_nodist" ]:
+        template = platform_values(defn, GRUB_PLATFORMS[0], suffix)
+        for platform in GRUB_PLATFORMS[1:]:
+            if template != platform_values(defn, platform, suffix):
+                return False
+
+    for suffix in [ "startup", "ldadd", "dependencies", "cflags", "ldflags", "cppflags", "ccasflags", "stripflags", "objcopyflags", "condition" ]:
+        template = platform_specific_values(defn, GRUB_PLATFORMS[0], "_" + suffix, suffix)
+        for platform in GRUB_PLATFORMS[1:]:
+            if template != platform_specific_values(defn, platform, "_" + suffix, suffix):
+                return False
+    for tag in [ "nostrip" ]:
+        template = platform_tagged(defn, GRUB_PLATFORMS[0], tag)
+        for platform in GRUB_PLATFORMS[1:]:
+            if template != platform_tagged(defn, platform, tag):
+                return False
+
+    return True
+
 def module(defn, platform):
     name = defn['name']
     set_canonical_name_suffix(".module")
@@ -649,11 +726,16 @@ def kernel(defn, platform):
 """if test x$(TARGET_APPLE_LINKER) = x1; then \
      $(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -wd1106 -nu -nd $< $@; \
    elif test ! -z '$(TARGET_OBJ2ELF)'; then \
-     cp $< $@.bin; $(TARGET_OBJ2ELF) $@.bin && cp $@.bin $@ || (rm -f $@.bin; exit 1); \
+     $(TARGET_OBJ2ELF) $< $@ || (rm -f $@; exit 1); \
    else cp $< $@; fi""",
 """if test x$(TARGET_APPLE_LINKER) = x1; then \
   $(TARGET_STRIP) -S -x $(""" + cname(defn) + """) -o $@.bin $<; \
   $(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -ed2016 -wd1106 -nu -nd $@.bin $@; \
+  rm -f $@.bin; \
+   elif test ! -z '$(TARGET_OBJ2ELF)'; then \
+     """  + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@.bin $< && \
+     $(TARGET_OBJ2ELF) $@.bin $@ || (rm -f $@; rm -f $@.bin; exit 1); \
+     rm -f $@.bin; \
 else """  + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@ $<; \
 fi"""))
 
@@ -681,7 +763,7 @@ def image(defn, platform):
 if test x$(TARGET_APPLE_LINKER) = x1; then \
   $(MACHO2IMG) $< $@; \
 else \
-  $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; \
+  $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version -R .ARM.exidx $< $@; \
 fi
 """)
 
@@ -756,6 +838,20 @@ def data(defn, platform):
     var_add("dist_" + installdir(defn) + "_DATA", platform_sources(defn, platform))
     gvar_add("dist_noinst_DATA", extra_dist(defn))
 
+def transform_data(defn, platform):
+    name = defn['name']
+
+    var_add(installdir(defn) + "_DATA", name)
+
+    rule(name, "$(top_builddir)/config.status " + platform_sources(defn, platform) + platform_dependencies(defn, platform), """
+(for x in """ + platform_sources(defn, platform) + """; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:-
+chmod a+x """ + name + """
+""")
+
+    gvar_add("CLEANFILES", name)
+    gvar_add("EXTRA_DIST", extra_dist(defn))
+    gvar_add("dist_noinst_DATA", platform_sources(defn, platform))
+
 def script(defn, platform):
     name = defn['name']
 
@@ -781,9 +877,12 @@ def rules(target, closure):
     seen_vars.clear()
 
     for defn in defparser.definitions.find_all(target):
-        foreach_enabled_platform(
-            defn,
-            lambda p: under_platform_specific_conditionals(defn, p, closure))
+        if is_platform_independent(defn):
+            under_platform_specific_conditionals(defn, GRUB_PLATFORMS[0], closure)
+        else:
+            foreach_enabled_platform(
+                defn,
+                lambda p: under_platform_specific_conditionals(defn, p, closure))
         # Remember that we've seen this target.
         seen_target.add(defn['name'])
 
@@ -791,8 +890,7 @@ parser = OptionParser(usage="%prog DEFINITION-FILES")
 _, args = parser.parse_args()
 
 for arg in args:
-    with open(arg) as f:
-        defparser.read_definitions(f)
+    defparser.read_definitions(arg)
 
 rules("module", module)
 rules("kernel", kernel)
@@ -801,6 +899,7 @@ rules("library", library)
 rules("program", program)
 rules("script", script)
 rules("data", data)
+rules("transform_data", transform_data)
 
 write_output(section='decl')
 write_output()