dtoc: add option to disable warnings

As dtoc now performs checks for valid driver names, when running dtoc
tests several warnings arise as these tests don't use valid driver
names.

This patch adds an option to disable those warning, which is only
intended for running tests.

Signed-off-by: Walter Lozano <walter.lozano@collabora.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index 1662d7d..cac422a 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -141,6 +141,7 @@
         _valid_nodes: A list of Node object with compatible strings
         _include_disabled: true to include nodes marked status = "disabled"
         _outfile: The current output file (sys.stdout or a real file)
+        _warning_disabled: true to disable warnings about driver names not found
         _lines: Stashed list of output lines for outputting in the future
         _aliases: Dict that hold aliases for compatible strings
             key: First compatible string declared in a node
@@ -151,12 +152,13 @@
                 U_BOOT_DRIVER_ALIAS(driver_alias, driver_name)
             value: Driver name declared with U_BOOT_DRIVER(driver_name)
     """
-    def __init__(self, dtb_fname, include_disabled):
+    def __init__(self, dtb_fname, include_disabled, warning_disabled):
         self._fdt = None
         self._dtb_fname = dtb_fname
         self._valid_nodes = None
         self._include_disabled = include_disabled
         self._outfile = None
+        self._warning_disabled = warning_disabled
         self._lines = []
         self._aliases = {}
         self._drivers = []
@@ -184,8 +186,9 @@
             compat_c_old = compat_c
             compat_c = self._driver_aliases.get(compat_c)
             if not compat_c:
-                print('WARNING: the driver %s was not found in the driver list'
-                      % (compat_c_old))
+                if not self._warning_disabled:
+                    print('WARNING: the driver %s was not found in the driver list'
+                          % (compat_c_old))
                 compat_c = compat_c_old
             else:
                 aliases_c = [compat_c_old] + aliases_c
@@ -639,7 +642,7 @@
             nodes_to_output.remove(node)
 
 
-def run_steps(args, dtb_file, include_disabled, output):
+def run_steps(args, dtb_file, include_disabled, output, warning_disabled=False):
     """Run all the steps of the dtoc tool
 
     Args:
@@ -651,7 +654,7 @@
     if not args:
         raise ValueError('Please specify a command: struct, platdata')
 
-    plat = DtbPlatdata(dtb_file, include_disabled)
+    plat = DtbPlatdata(dtb_file, include_disabled, warning_disabled)
     plat.scan_drivers()
     plat.scan_dtb()
     plat.scan_tree()
diff --git a/tools/dtoc/dtoc_test_invalid_driver.dts b/tools/dtoc/dtoc_test_invalid_driver.dts
new file mode 100644
index 0000000..914ac3e
--- /dev/null
+++ b/tools/dtoc/dtoc_test_invalid_driver.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test device tree file for dtoc
+ *
+ * Copyright 2017 Google, Inc
+ */
+
+/dts-v1/;
+
+/ {
+	spl-test {
+		u-boot,dm-pre-reloc;
+		compatible = "invalid";
+	};
+};
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index 91fc9d7..ae3ec50 100755
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -12,6 +12,7 @@
 import collections
 import os
 import struct
+import sys
 import unittest
 
 from dtoc import dtb_platdata
@@ -101,6 +102,10 @@
             print('Failures written to /tmp/binman.{expected,actual}')
         self.assertEquals(expected, actual)
 
+
+    def run_test(self, args, dtb_file, output):
+        dtb_platdata.run_steps(args, dtb_file, False, output, True)
+
     def test_name(self):
         """Test conversion of device tree names to C identifiers"""
         self.assertEqual('serial_at_0x12', conv_name_to_c('serial@0x12'))
@@ -154,12 +159,12 @@
         """Test output from a device tree file with no nodes"""
         dtb_file = get_dtb_file('dtoc_test_empty.dts')
         output = tools.GetOutputFilename('output')
-        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+        self.run_test(['struct'], dtb_file, output)
         with open(output) as infile:
             lines = infile.read().splitlines()
         self.assertEqual(HEADER.splitlines(), lines)
 
-        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+        self.run_test(['platdata'], dtb_file, output)
         with open(output) as infile:
             lines = infile.read().splitlines()
         self.assertEqual(C_HEADER.splitlines() + [''], lines)
@@ -168,7 +173,7 @@
         """Test output from some simple nodes with various types of data"""
         dtb_file = get_dtb_file('dtoc_test_simple.dts')
         output = tools.GetOutputFilename('output')
-        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+        self.run_test(['struct'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(HEADER + '''
@@ -193,7 +198,7 @@
 };
 ''', data)
 
-        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+        self.run_test(['platdata'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(C_HEADER + '''
@@ -272,7 +277,7 @@
         """Test output from a device tree file with a driver alias"""
         dtb_file = get_dtb_file('dtoc_test_driver_alias.dts')
         output = tools.GetOutputFilename('output')
-        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+        self.run_test(['struct'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(HEADER + '''
@@ -284,7 +289,7 @@
 #define dtd_sandbox_gpio_alias dtd_sandbox_gpio
 ''', data)
 
-        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+        self.run_test(['platdata'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(C_HEADER + '''
@@ -301,11 +306,39 @@
 
 ''', data)
 
+    def test_invalid_driver(self):
+        """Test output from a device tree file with an invalid driver"""
+        dtb_file = get_dtb_file('dtoc_test_invalid_driver.dts')
+        output = tools.GetOutputFilename('output')
+        with test_util.capture_sys_output() as (stdout, stderr):
+            dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+        with open(output) as infile:
+            data = infile.read()
+        self._CheckStrings(HEADER + '''
+struct dtd_invalid {
+};
+''', data)
+
+        with test_util.capture_sys_output() as (stdout, stderr):
+            dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+        with open(output) as infile:
+            data = infile.read()
+        self._CheckStrings(C_HEADER + '''
+static const struct dtd_invalid dtv_spl_test = {
+};
+U_BOOT_DEVICE(spl_test) = {
+\t.name\t\t= "invalid",
+\t.platdata\t= &dtv_spl_test,
+\t.platdata_size\t= sizeof(dtv_spl_test),
+};
+
+''', data)
+
     def test_phandle(self):
         """Test output from a node containing a phandle reference"""
         dtb_file = get_dtb_file('dtoc_test_phandle.dts')
         output = tools.GetOutputFilename('output')
-        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+        self.run_test(['struct'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(HEADER + '''
@@ -317,7 +350,7 @@
 };
 ''', data)
 
-        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+        self.run_test(['platdata'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(C_HEADER + '''
@@ -377,7 +410,7 @@
         """Test output from a node containing a phandle reference"""
         dtb_file = get_dtb_file('dtoc_test_phandle_single.dts')
         output = tools.GetOutputFilename('output')
-        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+        self.run_test(['struct'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(HEADER + '''
@@ -393,7 +426,7 @@
         """Test that phandle targets are generated before their references"""
         dtb_file = get_dtb_file('dtoc_test_phandle_reorder.dts')
         output = tools.GetOutputFilename('output')
-        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+        self.run_test(['platdata'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(C_HEADER + '''
@@ -423,7 +456,7 @@
                                 capture_stderr=True)
         output = tools.GetOutputFilename('output')
         with self.assertRaises(ValueError) as e:
-            dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+            self.run_test(['struct'], dtb_file, output)
         self.assertIn("Cannot parse 'clocks' in node 'phandle-source'",
                       str(e.exception))
 
@@ -433,7 +466,7 @@
                                 capture_stderr=True)
         output = tools.GetOutputFilename('output')
         with self.assertRaises(ValueError) as e:
-            dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+            self.run_test(['struct'], dtb_file, output)
         self.assertIn("Node 'phandle-target' has no '#clock-cells' property",
                       str(e.exception))
 
@@ -441,7 +474,7 @@
         """Test output from a node with multiple compatible strings"""
         dtb_file = get_dtb_file('dtoc_test_aliases.dts')
         output = tools.GetOutputFilename('output')
-        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+        self.run_test(['struct'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(HEADER + '''
@@ -452,7 +485,7 @@
 #define dtd_compat3 dtd_compat1
 ''', data)
 
-        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+        self.run_test(['platdata'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(C_HEADER + '''
@@ -471,7 +504,7 @@
         """Test output from a node with a 'reg' property with na=2, ns=2"""
         dtb_file = get_dtb_file('dtoc_test_addr64.dts')
         output = tools.GetOutputFilename('output')
-        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+        self.run_test(['struct'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(HEADER + '''
@@ -486,7 +519,7 @@
 };
 ''', data)
 
-        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+        self.run_test(['platdata'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(C_HEADER + '''
@@ -523,7 +556,7 @@
         """Test output from a node with a 'reg' property with na=1, ns=1"""
         dtb_file = get_dtb_file('dtoc_test_addr32.dts')
         output = tools.GetOutputFilename('output')
-        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+        self.run_test(['struct'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(HEADER + '''
@@ -535,7 +568,7 @@
 };
 ''', data)
 
-        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+        self.run_test(['platdata'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(C_HEADER + '''
@@ -563,7 +596,7 @@
         """Test output from a node with a 'reg' property with na=2, ns=1"""
         dtb_file = get_dtb_file('dtoc_test_addr64_32.dts')
         output = tools.GetOutputFilename('output')
-        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+        self.run_test(['struct'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(HEADER + '''
@@ -578,7 +611,7 @@
 };
 ''', data)
 
-        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+        self.run_test(['platdata'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(C_HEADER + '''
@@ -615,7 +648,7 @@
         """Test output from a node with a 'reg' property with na=1, ns=2"""
         dtb_file = get_dtb_file('dtoc_test_addr32_64.dts')
         output = tools.GetOutputFilename('output')
-        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+        self.run_test(['struct'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(HEADER + '''
@@ -630,7 +663,7 @@
 };
 ''', data)
 
-        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+        self.run_test(['platdata'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(C_HEADER + '''
@@ -669,7 +702,7 @@
         dtb_file = get_dtb_file('dtoc_test_bad_reg.dts', capture_stderr=True)
         output = tools.GetOutputFilename('output')
         with self.assertRaises(ValueError) as e:
-            dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+            self.run_test(['struct'], dtb_file, output)
         self.assertIn("Node 'spl-test' reg property is not an int",
                       str(e.exception))
 
@@ -679,7 +712,7 @@
         dtb_file = get_dtb_file('dtoc_test_bad_reg2.dts', capture_stderr=True)
         output = tools.GetOutputFilename('output')
         with self.assertRaises(ValueError) as e:
-            dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+            self.run_test(['struct'], dtb_file, output)
         self.assertIn("Node 'spl-test' reg property has 3 cells which is not a multiple of na + ns = 1 + 1)",
                       str(e.exception))
 
@@ -687,7 +720,7 @@
         """Test that a subequent node can add a new property to a struct"""
         dtb_file = get_dtb_file('dtoc_test_add_prop.dts')
         output = tools.GetOutputFilename('output')
-        dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+        self.run_test(['struct'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(HEADER + '''
@@ -697,7 +730,7 @@
 };
 ''', data)
 
-        dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+        self.run_test(['platdata'], dtb_file, output)
         with open(output) as infile:
             data = infile.read()
         self._CheckStrings(C_HEADER + '''
@@ -725,12 +758,12 @@
         """Test output to stdout"""
         dtb_file = get_dtb_file('dtoc_test_simple.dts')
         with test_util.capture_sys_output() as (stdout, stderr):
-            dtb_platdata.run_steps(['struct'], dtb_file, False, '-')
+            self.run_test(['struct'], dtb_file, '-')
 
     def testNoCommand(self):
         """Test running dtoc without a command"""
         with self.assertRaises(ValueError) as e:
-            dtb_platdata.run_steps([], '', False, '')
+            self.run_test([], '', '')
         self.assertIn("Please specify a command: struct, platdata",
                       str(e.exception))
 
@@ -739,6 +772,6 @@
         dtb_file = get_dtb_file('dtoc_test_simple.dts')
         output = tools.GetOutputFilename('output')
         with self.assertRaises(ValueError) as e:
-            dtb_platdata.run_steps(['invalid-cmd'], dtb_file, False, output)
+            self.run_test(['invalid-cmd'], dtb_file, output)
         self.assertIn("Unknown command 'invalid-cmd': (use: struct, platdata)",
                       str(e.exception))