示例#1
0
    def test_scan_dirs(self):
        """Test scanning of source directories"""
        def add_file(fname):
            pathname = os.path.join(indir, fname)
            dirname = os.path.dirname(pathname)
            os.makedirs(dirname, exist_ok=True)
            tools.WriteFile(pathname, '', binary=False)
            fname_list.append(pathname)

        try:
            indir = tempfile.mkdtemp(prefix='dtoc.')

            fname_list = []
            add_file('fname.c')
            add_file('.git/ignoreme.c')
            add_file('dir/fname2.c')
            add_file('build-sandbox/ignoreme2.c')

            # Mock out scan_driver and check that it is called with the
            # expected files
            with mock.patch.object(src_scan.Scanner, "scan_driver") as mocked:
                scan = src_scan.Scanner(indir, None)
                scan.scan_drivers()
            self.assertEqual(2, len(mocked.mock_calls))
            self.assertEqual(mock.call(fname_list[0]), mocked.mock_calls[0])
            # .git file should be ignored
            self.assertEqual(mock.call(fname_list[2]), mocked.mock_calls[1])
        finally:
            shutil.rmtree(indir)
示例#2
0
    def test_struct_scan(self):
        """Test collection of struct info"""
        buff = '''
/* some comment */
struct some_struct1 {
	struct i2c_msg *msgs;
	uint nmsgs;
};
'''
        scan = src_scan.Scanner(None, False, None)
        scan._basedir = os.path.join(OUR_PATH, '..', '..')
        scan._parse_structs('arch/arm/include/asm/file.h', buff)
        self.assertIn('some_struct1', scan._structs)
        struc = scan._structs['some_struct1']
        self.assertEqual('some_struct1', struc.name)
        self.assertEqual('asm/file.h', struc.fname)

        buff = '''
/* another comment */
struct another_struct {
	int speed_hz;
	int max_transaction_bytes;
};
'''
        scan._parse_structs('include/file2.h', buff)
        self.assertIn('another_struct', scan._structs)
        struc = scan._structs['another_struct']
        self.assertEqual('another_struct', struc.name)
        self.assertEqual('file2.h', struc.fname)

        self.assertEqual(2, len(scan._structs))

        self.assertEqual("Struct(name='another_struct', fname='file2.h')",
                         str(struc))
示例#3
0
    def test_priv(self):
        """Test collection of struct info from drivers"""
        buff = '''
static const struct udevice_id test_ids[] = {
	{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
	{ }
};

U_BOOT_DRIVER(testing) = {
	.name	= "testing",
	.id	= UCLASS_I2C,
	.of_match = test_ids,
	.priv_auto	= sizeof(struct some_priv),
	.plat_auto = sizeof(struct some_plat),
	.per_child_auto	= sizeof(struct some_cpriv),
	.per_child_plat_auto = sizeof(struct some_cplat),
	DM_PHASE(tpl)
	DM_HEADER(<i2c.h>)
	DM_HEADER(<asm/clk.h>)
};
'''
        scan = src_scan.Scanner(None, False, None)
        scan._parse_driver('file.c', buff)
        self.assertIn('testing', scan._drivers)
        drv = scan._drivers['testing']
        self.assertEqual('testing', drv.name)
        self.assertEqual('UCLASS_I2C', drv.uclass_id)
        self.assertEqual({'nvidia,tegra114-i2c': 'TYPE_114'}, drv.compat)
        self.assertEqual('some_priv', drv.priv)
        self.assertEqual('some_plat', drv.plat)
        self.assertEqual('some_cpriv', drv.child_priv)
        self.assertEqual('some_cplat', drv.child_plat)
        self.assertEqual('tpl', drv.phase)
        self.assertEqual(['<i2c.h>', '<asm/clk.h>'], drv.headers)
        self.assertEqual(1, len(scan._drivers))
示例#4
0
 def test_additional(self):
     """Test with additional drivers to scan"""
     scan = src_scan.Scanner(
         None, [None, '', 'tools/dtoc/test/dtoc_test_scan_drivers.cxx'])
     scan.scan_drivers()
     self.assertIn('sandbox_gpio_alias2', scan._driver_aliases)
     self.assertEqual('sandbox_gpio',
                      scan._driver_aliases['sandbox_gpio_alias2'])
示例#5
0
 def test_simple(self):
     """Simple test of scanning drivers"""
     scan = src_scan.Scanner(None, None)
     scan.scan_drivers()
     self.assertIn('sandbox_gpio', scan._drivers)
     self.assertIn('sandbox_gpio_alias', scan._driver_aliases)
     self.assertEqual('sandbox_gpio',
                      scan._driver_aliases['sandbox_gpio_alias'])
     self.assertNotIn('sandbox_gpio_alias2', scan._driver_aliases)
示例#6
0
    def test_struct_scan_errors(self):
        """Test scanning a header file with an invalid unicode file"""
        output = tools.GetOutputFilename('output.h')
        tools.WriteFile(output, b'struct this is a test \x81 of bad unicode')

        scan = src_scan.Scanner(None, None)
        with test_util.capture_sys_output() as (stdout, _):
            scan.scan_header(output)
        self.assertIn('due to unicode error', stdout.getvalue())
示例#7
0
def run_steps(args,
              dtb_file,
              include_disabled,
              output,
              output_dirs,
              warning_disabled=False,
              drivers_additional=None,
              basedir=None):
    """Run all the steps of the dtoc tool

    Args:
        args (list): List of non-option arguments provided to the problem
        dtb_file (str): Filename of dtb file to process
        include_disabled (bool): True to include disabled nodes
        output (str): Name of output file (None for stdout)
        output_dirs (tuple of str):
            Directory to put C output files
            Directory to put H output files
        warning_disabled (bool): True to avoid showing warnings about missing
            drivers
        drivers_additional (list): List of additional drivers to use during
            scanning
        basedir (str): Base directory of U-Boot source code. Defaults to the
            grandparent of this file's directory
    Raises:
        ValueError: if args has no command, or an unknown command
    """
    if not args:
        raise ValueError('Please specify a command: struct, platdata, all')
    if output and output_dirs and any(output_dirs):
        raise ValueError('Must specify either output or output_dirs, not both')

    scan = src_scan.Scanner(basedir, warning_disabled, drivers_additional)
    plat = DtbPlatdata(scan, dtb_file, include_disabled)
    scan.scan_drivers()
    plat.scan_dtb()
    plat.scan_tree()
    plat.scan_reg_sizes()
    plat.setup_output_dirs(output_dirs)
    plat.scan_structs()
    plat.scan_phandles()

    cmds = args[0].split(',')
    if 'all' in cmds:
        cmds = sorted(OUTPUT_FILES.keys())
    for cmd in cmds:
        outfile = OUTPUT_FILES.get(cmd)
        if not outfile:
            raise ValueError("Unknown command '%s': (use: %s)" %
                             (cmd, ', '.join(sorted(OUTPUT_FILES.keys()))))
        plat.setup_output(outfile.ftype,
                          outfile.fname if output_dirs else output)
        plat.out_header(outfile)
        outfile.method(plat)
    plat.finish_output()
示例#8
0
    def test_uclass_scan_errors(self):
        """Test detection of uclass scanning errors"""
        buff = '''
UCLASS_DRIVER(i2c) = {
	.name		= "i2c",
};

'''
        scan = src_scan.Scanner(None, None)
        with self.assertRaises(ValueError) as exc:
            scan._parse_uclass_driver('file.c', buff)
        self.assertIn("file.c: Cannot parse uclass ID in driver 'i2c'",
                      str(exc.exception))
示例#9
0
    def setup_dup_drivers(self, name, phase=''):
        """Set up for a duplcate test

        Returns:
            tuple:
                Scanner to use
                Driver record for first driver
                Text of second driver declaration
                Node for driver 1
        """
        driver1 = '''
static const struct udevice_id test_ids[] = {
	{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
	{ }
};

U_BOOT_DRIVER(%s) = {
	.name	= "testing",
	.id	= UCLASS_I2C,
	.of_match = test_ids,
	%s
};
''' % (name, 'DM_PHASE(%s)' % phase if phase else '')
        driver2 = '''
static const struct udevice_id test_ids[] = {
	{ .compatible = "nvidia,tegra114-dvc" },
	{ }
};

U_BOOT_DRIVER(%s) = {
	.name	= "testing",
	.id	= UCLASS_RAM,
	.of_match = test_ids,
};
''' % name
        scan = src_scan.Scanner(None, None, phase)
        scan._parse_driver('file1.c', driver1)
        self.assertIn(name, scan._drivers)
        drv1 = scan._drivers[name]

        prop = FakeProp()
        prop.name = 'compatible'
        prop.value = 'nvidia,tegra114-i2c'
        node = FakeNode()
        node.name = 'testing'
        node.props = {'compatible': prop}

        # get_normalized_compat_name() uses this to check for root node
        node.parent = FakeNode()

        return scan, drv1, driver2, node
示例#10
0
    def test_sequence(self):
        """Test assignment of sequence numnbers"""
        scan = src_scan.Scanner(None, None, '')
        node = FakeNode()
        uc = src_scan.UclassDriver('UCLASS_I2C')
        node.uclass = uc
        node.driver = True
        node.seq = -1
        node.path = 'mypath'
        uc.alias_num_to_node[2] = node

        # This should assign 3 (after the 2 that exists)
        seq = scan.assign_seq(node)
        self.assertEqual(3, seq)
        self.assertEqual({'mypath': 3}, uc.alias_path_to_num)
        self.assertEqual({2: node, 3: node}, uc.alias_num_to_node)
示例#11
0
    def test_unicode_error(self):
        """Test running dtoc with an invalid unicode file

        To be able to perform this test without adding a weird text file which
        would produce issues when using checkpatch.pl or patman, generate the
        file at runtime and then process it.
        """
        driver_fn = '/tmp/' + next(tempfile._get_candidate_names())
        with open(driver_fn, 'wb+') as fout:
            fout.write(b'\x81')

        scan = src_scan.Scanner(None, [driver_fn])
        with test_util.capture_sys_output() as (stdout, _):
            scan.scan_drivers()
        self.assertRegex(stdout.getvalue(),
                         r"Skipping file '.*' due to unicode error\s*")
示例#12
0
    def test_normalized_name(self):
        """Test operation of get_normalized_compat_name()"""
        prop = FakeProp()
        prop.name = 'compatible'
        prop.value = 'rockchip,rk3288-grf'
        node = FakeNode()
        node.props = {'compatible': prop}

        # get_normalized_compat_name() uses this to check for root node
        node.parent = FakeNode()

        scan = src_scan.Scanner(None, None)
        with test_util.capture_sys_output() as (stdout, _):
            name, aliases = scan.get_normalized_compat_name(node)
        self.assertEqual('rockchip_rk3288_grf', name)
        self.assertEqual([], aliases)
        self.assertEqual(1, len(scan._missing_drivers))
        self.assertEqual({'rockchip_rk3288_grf'}, scan._missing_drivers)
        self.assertEqual('', stdout.getvalue().strip())
        self.assertEqual(EXPECT_WARN, scan._warnings)

        i2c = 'I2C_UCLASS'
        compat = {
            'rockchip,rk3288-grf': 'ROCKCHIP_SYSCON_GRF',
            'rockchip,rk3288-srf': None
        }
        drv = src_scan.Driver('fred', 'fred.c')
        drv.uclass_id = i2c
        drv.compat = compat
        scan._drivers['rockchip_rk3288_grf'] = drv

        scan._driver_aliases['rockchip_rk3288_srf'] = 'rockchip_rk3288_grf'

        with test_util.capture_sys_output() as (stdout, _):
            name, aliases = scan.get_normalized_compat_name(node)
        self.assertEqual('', stdout.getvalue().strip())
        self.assertEqual('rockchip_rk3288_grf', name)
        self.assertEqual([], aliases)
        self.assertEqual(EXPECT_WARN, scan._warnings)

        prop.value = 'rockchip,rk3288-srf'
        with test_util.capture_sys_output() as (stdout, _):
            name, aliases = scan.get_normalized_compat_name(node)
        self.assertEqual('', stdout.getvalue().strip())
        self.assertEqual('rockchip_rk3288_grf', name)
        self.assertEqual(['rockchip_rk3288_srf'], aliases)
        self.assertEqual(EXPECT_WARN, scan._warnings)
示例#13
0
    def scan_compat_warning(self):
        """Test a missing .compatible in the driver"""
        buff = '''
static const struct udevice_id tegra_i2c_ids[] = {
	{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
	{ }
};

U_BOOT_DRIVER(i2c_tegra) = {
	.name	= "i2c_tegra",
	.id	= UCLASS_I2C,
};
'''
        scan = src_scan.Scanner(None, None)
        scan._parse_driver('file.c', buff)
        self.assertEqual({'i2c_tegra': {'Missing .compatible in file.c'}},
                         scan._warnings)
示例#14
0
 def test_scan(self):
     """Test scanning of a driver"""
     fname = os.path.join(OUR_PATH, '..', '..', 'drivers/i2c/tegra_i2c.c')
     buff = tools.ReadFile(fname, False)
     scan = src_scan.Scanner(None, None)
     scan._parse_driver(fname, buff)
     self.assertIn('i2c_tegra', scan._drivers)
     drv = scan._drivers['i2c_tegra']
     self.assertEqual('i2c_tegra', drv.name)
     self.assertEqual('UCLASS_I2C', drv.uclass_id)
     self.assertEqual(
         {
             'nvidia,tegra114-i2c': 'TYPE_114',
             'nvidia,tegra20-i2c': 'TYPE_STD',
             'nvidia,tegra20-i2c-dvc': 'TYPE_DVC'
         }, drv.compat)
     self.assertEqual('i2c_bus', drv.priv)
     self.assertEqual(1, len(scan._drivers))
示例#15
0
    def test_scan_errors(self):
        """Test detection of scanning errors"""
        buff = '''
static const struct udevice_id tegra_i2c_ids2[] = {
	{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
	{ }
};

U_BOOT_DRIVER(i2c_tegra) = {
	.name	= "i2c_tegra",
	.id	= UCLASS_I2C,
	.of_match = tegra_i2c_ids,
};
'''
        scan = src_scan.Scanner(None, None)
        with self.assertRaises(ValueError) as exc:
            scan._parse_driver('file.c', buff)
        self.assertIn(
            "file.c: Unknown compatible var 'tegra_i2c_ids' (found: tegra_i2c_ids2)",
            str(exc.exception))
示例#16
0
    def test_of_match(self):
        """Test detection of of_match_ptr() member"""
        buff = '''
static const struct udevice_id tegra_i2c_ids[] = {
	{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
	{ }
};

U_BOOT_DRIVER(i2c_tegra) = {
	.name	= "i2c_tegra",
	.id	= UCLASS_I2C,
	.of_match = of_match_ptr(tegra_i2c_ids),
};
'''
        scan = src_scan.Scanner(None, None)
        scan._parse_driver('file.c', buff)
        self.assertIn('i2c_tegra', scan._drivers)
        drv = scan._drivers['i2c_tegra']
        self.assertEqual('i2c_tegra', drv.name)
        self.assertEqual('', drv.phase)
        self.assertEqual([], drv.headers)
示例#17
0
    def test_uclass_scan(self):
        """Test collection of uclass-driver info"""
        buff = '''
UCLASS_DRIVER(i2c) = {
	.id		= UCLASS_I2C,
	.name		= "i2c",
	.flags		= DM_UC_FLAG_SEQ_ALIAS,
	.priv_auto	= sizeof(struct some_priv),
	.per_device_auto	= sizeof(struct per_dev_priv),
	.per_device_plat_auto	= sizeof(struct per_dev_plat),
	.per_child_auto	= sizeof(struct per_child_priv),
	.per_child_plat_auto	= sizeof(struct per_child_plat),
	.child_post_bind = i2c_child_post_bind,
};

'''
        scan = src_scan.Scanner(None, None)
        scan._parse_uclass_driver('file.c', buff)
        self.assertIn('UCLASS_I2C', scan._uclass)
        drv = scan._uclass['UCLASS_I2C']
        self.assertEqual('i2c', drv.name)
        self.assertEqual('UCLASS_I2C', drv.uclass_id)
        self.assertEqual('some_priv', drv.priv)
        self.assertEqual('per_dev_priv', drv.per_dev_priv)
        self.assertEqual('per_dev_plat', drv.per_dev_plat)
        self.assertEqual('per_child_priv', drv.per_child_priv)
        self.assertEqual('per_child_plat', drv.per_child_plat)
        self.assertEqual(1, len(scan._uclass))

        drv2 = copy.deepcopy(drv)
        self.assertEqual(drv, drv2)
        drv2.priv = 'other_priv'
        self.assertNotEqual(drv, drv2)

        # The hashes only depend on the uclass ID, so should be equal
        self.assertEqual(drv.__hash__(), drv2.__hash__())

        self.assertEqual("UclassDriver(name='i2c', uclass_id='UCLASS_I2C')",
                         str(drv))
示例#18
0
def run_steps(args,
              dtb_file,
              include_disabled,
              output,
              output_dirs,
              phase,
              instantiate,
              warning_disabled=False,
              drivers_additional=None,
              basedir=None,
              scan=None):
    """Run all the steps of the dtoc tool

    Args:
        args (list): List of non-option arguments provided to the problem
        dtb_file (str): Filename of dtb file to process
        include_disabled (bool): True to include disabled nodes
        output (str): Name of output file (None for stdout)
        output_dirs (tuple of str):
            Directory to put C output files
            Directory to put H output files
        phase: The phase of U-Boot that we are generating data for, e.g. 'spl'
             or 'tpl'. None if not known
        instantiate: Instantiate devices so they don't need to be bound at
            run-time
        warning_disabled (bool): True to avoid showing warnings about missing
            drivers
        drivers_additional (list): List of additional drivers to use during
            scanning
        basedir (str): Base directory of U-Boot source code. Defaults to the
            grandparent of this file's directory
        scan (src_src.Scanner): Scanner from a previous run. This can help speed
            up tests. Use None for normal operation

    Returns:
        DtbPlatdata object

    Raises:
        ValueError: if args has no command, or an unknown command
    """
    if not args:
        raise ValueError('Please specify a command: struct, platdata, all')
    if output and output_dirs and any(output_dirs):
        raise ValueError('Must specify either output or output_dirs, not both')

    if not scan:
        scan = src_scan.Scanner(basedir, warning_disabled, drivers_additional,
                                phase)
        scan.scan_drivers()
        do_process = True
    else:
        do_process = False
    plat = DtbPlatdata(scan, dtb_file, include_disabled, instantiate)
    plat.scan_dtb()
    plat.scan_tree(add_root=instantiate)
    plat.prepare_nodes()
    plat.scan_reg_sizes()
    plat.setup_output_dirs(output_dirs)
    plat.scan_structs()
    plat.scan_phandles()
    plat.process_nodes(instantiate)
    plat.read_aliases()
    plat.assign_seqs()

    # Figure out what output files we plan to generate
    output_files = OUTPUT_FILES_COMMON
    if instantiate:
        output_files.update(OUTPUT_FILES_INST)
    else:
        output_files.update(OUTPUT_FILES_NOINST)

    cmds = args[0].split(',')
    if 'all' in cmds:
        cmds = sorted(output_files.keys())
    for cmd in cmds:
        outfile = output_files.get(cmd)
        if not outfile:
            raise ValueError("Unknown command '%s': (use: %s)" %
                             (cmd, ', '.join(sorted(output_files.keys()))))
        plat.setup_output(outfile.ftype,
                          outfile.fname if output_dirs else output)
        plat.out_header(outfile)
        outfile.method(plat)
    plat.finish_output()
    return plat
示例#19
0
    def test_scan_warnings(self):
        """Test detection of scanning warnings"""
        buff = '''
static const struct udevice_id tegra_i2c_ids[] = {
	{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
	{ }
};

U_BOOT_DRIVER(i2c_tegra) = {
	.name	= "i2c_tegra",
	.id	= UCLASS_I2C,
	.of_match = tegra_i2c_ids + 1,
};
'''
        # The '+ 1' above should generate a warning

        prop = FakeProp()
        prop.name = 'compatible'
        prop.value = 'rockchip,rk3288-grf'
        node = FakeNode()
        node.props = {'compatible': prop}

        # get_normalized_compat_name() uses this to check for root node
        node.parent = FakeNode()

        scan = src_scan.Scanner(None, None)
        scan._parse_driver('file.c', buff)
        self.assertEqual(
            {
                'i2c_tegra': {
                    "file.c: Warning: unexpected suffix ' + 1' on .of_match line for compat 'tegra_i2c_ids'"
                }
            }, scan._warnings)

        tprop = FakeProp()
        tprop.name = 'compatible'
        tprop.value = 'nvidia,tegra114-i2c'
        tnode = FakeNode()
        tnode.props = {'compatible': tprop}

        # get_normalized_compat_name() uses this to check for root node
        tnode.parent = FakeNode()

        with test_util.capture_sys_output() as (stdout, _):
            scan.get_normalized_compat_name(node)
            scan.get_normalized_compat_name(tnode)
        self.assertEqual('', stdout.getvalue().strip())

        self.assertEqual(2, len(scan._missing_drivers))
        self.assertEqual({'rockchip_rk3288_grf', 'nvidia_tegra114_i2c'},
                         scan._missing_drivers)
        with test_util.capture_sys_output() as (stdout, _):
            scan.show_warnings()
        self.assertIn('rockchip_rk3288_grf', stdout.getvalue())

        # This should show just the rockchip warning, since the tegra driver
        # is not in self._missing_drivers
        scan._missing_drivers.remove('nvidia_tegra114_i2c')
        with test_util.capture_sys_output() as (stdout, _):
            scan.show_warnings()
        self.assertIn('rockchip_rk3288_grf', stdout.getvalue())
        self.assertNotIn('tegra_i2c_ids', stdout.getvalue())

        # Do a similar thing with used drivers. By marking the tegra driver as
        # used, the warning related to that driver will be shown
        drv = scan._drivers['i2c_tegra']
        drv.used = True
        with test_util.capture_sys_output() as (stdout, _):
            scan.show_warnings()
        self.assertIn('rockchip_rk3288_grf', stdout.getvalue())
        self.assertIn('tegra_i2c_ids', stdout.getvalue())

        # Add a warning to make sure multiple warnings are shown
        scan._warnings['i2c_tegra'].update(
            scan._warnings['nvidia_tegra114_i2c'])
        del scan._warnings['nvidia_tegra114_i2c']
        with test_util.capture_sys_output() as (stdout, _):
            scan.show_warnings()
        self.assertEqual(
            '''i2c_tegra: WARNING: the driver nvidia_tegra114_i2c was not found in the driver list
         : file.c: Warning: unexpected suffix ' + 1' on .of_match line for compat 'tegra_i2c_ids'

rockchip_rk3288_grf: WARNING: the driver rockchip_rk3288_grf was not found in the driver list

''', stdout.getvalue())
        self.assertIn('tegra_i2c_ids', stdout.getvalue())