pax_global_header00006660000000000000000000000064142772061420014517gustar00rootroot0000000000000052 comment=9c931b41778b6ea15153480b65a2391b7ddafd61 dt-schema-2022.08.2/000077500000000000000000000000001427720614200137015ustar00rootroot00000000000000dt-schema-2022.08.2/.github/000077500000000000000000000000001427720614200152415ustar00rootroot00000000000000dt-schema-2022.08.2/.github/workflows/000077500000000000000000000000001427720614200172765ustar00rootroot00000000000000dt-schema-2022.08.2/.github/workflows/ci.yml000066400000000000000000000017721427720614200204230ustar00rootroot00000000000000 on: [push, pull_request] jobs: build: runs-on: ubuntu-latest strategy: fail-fast: false matrix: python-version: ['3.7', '3.8', '3.9', '3.10'] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | sudo apt-get -qq -y install device-tree-compiler python -m pip install --upgrade pip python -m pip install flake8 pip install . - name: Lint with flake8 run: | # stop the build if there are Python syntax errors or undefined names flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Test run: | test/test-dt-validate.py dt-schema-2022.08.2/.github/workflows/publish.yml000066400000000000000000000011371427720614200214710ustar00rootroot00000000000000name: Upload Python Package on: push: tags: - 'v*' - '!v*-pre' jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 with: python-version: '3.x' - name: Install dependencies run: | python -m pip install --upgrade pip pip install build - name: Build package run: python -m build - name: Publish package uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} dt-schema-2022.08.2/.gitignore000066400000000000000000000000571427720614200156730ustar00rootroot00000000000000.eggs __pycache__ build dist dtschema.egg-info dt-schema-2022.08.2/LICENSE.txt000066400000000000000000000024221427720614200155240ustar00rootroot00000000000000Copyright 2018-2019 Linaro Ltd. Copyright 2018-2020 Arm Ltd. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. dt-schema-2022.08.2/README.md000066400000000000000000000131341427720614200151620ustar00rootroot00000000000000# Tooling for devicetree validation using YAML and jsonschema This repository contains test code for devicetree schema validation using the [json-schema](http://json-schema.org/documentation.html) vocabulary. Schema files are written in YAML (a superset of JSON), and operate on the YAML encoding of Devicetree data. Devicetree data must be transcoded from DTS to YAML before being used by this tool. ## Data Model To understand how validation works, it is important to understand how schema data is organized and used. If you're reading this, I assume you're already familiar with Devicetree and the .dts file format. In this repository you will find three kinds of files; *YAML Devicetrees*, *Schemas* and *Meta-Schemas*. ### *YAML Devicetrees* Found under `./test` *YAML Devicetrees* files are regular .dts files transcoded into a YAML representation. There is no special information in these files. They are used as test cases against the validation tooling. Validation of .dtb files is now supported and preferred over YAML DT encoding. ### *Devicetree Schemas* Found under `./dtschema/schemas` *Devicetree Schemas* describe the format of devicetree data. The raw Devicetree file format is very open ended and doesn't restrict how data is encoded. Hence, it is easy to make mistakes when writing a Devicetree. Schema files impose constraints on what data can be put into a devicetree. As the foundation, a single core schema describes all the common property types that every devicetree node must match. e.g. In every node the 'compatible' property must be an array of strings. However, most devicetree data is heterogeneous as each device binding requires a different set of data, therefore multiple schema files are used to capture the data format of an entire devicetree. When validating, the tool will load all the schema files it can find and then iterate over all the nodes of the devicetree. For each node, the tool will determine which schema(s) are applicable and make sure the node data matches the schema constraints. Nodes failing a schema test will emit an error. Nodes that don't match any schema will emit a warning. As a developer, you would write a devicetree schema file for each new device binding that you create and add it to the `./schemas` directory. Schema files also have the dual purpose of documenting a binding. When you define a new binding, you only have to create one file that contains both the machine-verifiable data format and the documentation. Documentation generation tools are being written to extract documentation from a schema file and emit a format that can be included in the devicetree specification documents. Devicetree Schema files are normal YAML files using the jsonschema vocabulary. The Devicetree Schema files are simplified to make them more compact. The default for arrays in json-schema is they are variable sized. This can be restricted by defining 'minItems', 'maxItems', and 'additionalItems'. For DeviceTree Schemas, a fixed size is desired in most cases, so these properties are added based on the size of 'items' list. The YAML DeviceTree format also makes all string values an array and scalar values a matrix (in order to define groupings) even when only a single value is present. Single entries in schemas are fixed up to match this encoding. ### *Devicetree Meta-Schemas* Found in `./dtschema/meta-schemas` *Devicetree Meta-Schemas* describe the data format of Devicetree Schema files. The Meta-schemas make sure all the binding schemas are in the correct format and the tool will emit an error if the format is incorrect. As a developer you normally will not need to write metaschema files. Devicetree Meta-Schema files are normal YAML files using the jsonschema vocabulary. ## Usage There are several tools available in the *tools/* directory. `tools/dt-doc-validate` This tool takes a schema file(s) or directory of schema files and validates them against the DT meta-schema. `tools/dt-mk-schema` This tool takes user-provided schema file(s) plus the core schema files in this repo, removes everything not needed for validation, applies fix-ups to the schemas, and outputs a single file with the processed schema. This step is done separately to speed up subsequent validation of YAML Devicetrees. `tools/dt-validate` This tool takes user-provided YAML Devicetree(s) and either a schema directory or pre-processed schema file and validates the YAML Devicetree against the schema. ## Installing The project and its dependencies can be installed with pip: ``` pip3 install dtschema ``` or directly from git: ``` pip3 install git+https://github.com/devicetree-org/dt-schema.git@main ``` All executables will be installed. Ensure ~/.local/bin is in the PATH. For development, clone the git repository manually and run pip on local tree:: ``` git clone https://github.com/devicetree-org/dt-schema.git cd dt-schema pip3 install -e . ``` ## Dependencies Note: The above installation instructions handle all of the dependencies automatically. This code depends on Python 3 with the pylibfdt, ruamel.yaml, rfc3987, and jsonschema libraries. Installing pylibfdt depends on the 'swig' program. On Debian/Ubuntu, the dependencies can be installed with apt and/or pip. The rfc3987 module is not packaged, so pip must be used: ``` sudo apt install swig sudo apt install python3 python3-ruamel.yaml pip3 install rfc3987 ``` ### jsonschema This code depends on at least version 4.1.2 of the [Python jsonschema](https://github.com/Julian/jsonschema/tree/master) library for Draft 2019-09 support. The module can be installed directly from github with pip: ``` pip3 install git+https://github.com/Julian/jsonschema.git ``` dt-schema-2022.08.2/dtschema/000077500000000000000000000000001427720614200154715ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/.gitignore000066400000000000000000000000131427720614200174530ustar00rootroot00000000000000version.py dt-schema-2022.08.2/dtschema/__init__.py000066400000000000000000000005021427720614200175770ustar00rootroot00000000000000from dtschema.lib import ( add_schema_path, load_schema, load, set_schemas, DTValidator, format_error, extract_compatibles, extract_types, get_undocumented_compatibles, property_get_type, property_get_type_dim, sized_int, ) from dtschema.version import ( __version__ ) dt-schema-2022.08.2/dtschema/dtb.py000066400000000000000000000332551427720614200166240ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2021-2022 Arm Ltd. # Python library for Devicetree schema validation import sys import struct import pprint import libfdt from libfdt import QUIET_NOTFOUND import dtschema u8 = struct.Struct('B') s8 = struct.Struct('b') u16 = struct.Struct('>H') s16 = struct.Struct('>h') u32 = struct.Struct('>L') s32 = struct.Struct('>l') u64 = struct.Struct('>Q') s64 = struct.Struct('>q') type_format = { 'int8': s8, 'uint8': u8, 'int16': s16, 'uint16': u16, 'int32': s32, 'uint32': u32, 'int64': s64, 'uint64': u64, 'phandle': u32 } def bytes_to_string(b): try: strings = b.decode(encoding='ascii').split('\0') count = len(strings) - 1 if count > 0 and not len(strings[-1]): for string in strings[:-1]: if not string: continue if not string.isprintable(): break else: return strings[:-1] except: return None def get_stride(len, dim): match = 0 if min(dim) == 0: return 0 for d in range(dim[0], dim[1] + 1): if not len % d: match += 1 stride = d if match == 1: return stride return 0 def prop_value(nodename, p): # First, check for a boolean type if not len(p): return True dim = None data = bytes(p) fmt = None if nodename in {'__fixups__', 'aliases'}: return data[:-1].decode(encoding='ascii').split('\0') prop_types = dtschema.property_get_type(p.name) if 'node' in prop_types: prop_types.remove('node') if len(prop_types) > 1: if {'string', 'string-array'} & set(prop_types): str = bytes_to_string(data) if str: return str # Assuming only one other type try: fmt = set(prop_types).difference({'string', 'string-array'}).pop() except: return data elif 'flag' in prop_types and len(data): fmt = set(prop_types).difference({'flag'}).pop() else: #print(p.name + ': multiple types found', file=sys.stderr) fmt = None elif len(prop_types) == 1: fmt = prop_types[0] if not fmt: # Primarily for aliases properties try: s = data.decode(encoding='ascii') if s.endswith('\0'): s = s[:-1] if s.isprintable(): return [s] except: pass if not len(data) % 4: fmt = 'uint32-array' else: #print(p.name + ': no type found', file=sys.stderr) return data if fmt.startswith('string'): return data[:-1].decode(encoding='ascii').split('\0') if fmt == 'flag': if len(data): print('{prop}: boolean property with value {val}'.format(prop=p.name, val=data), file=sys.stderr) return data return True val_int = list() #print(p.name, fmt, bytes(p)) try: type_struct = type_format[fmt.split('-', 1)[0]] for i in type_struct.iter_unpack(data): val_int += [dtschema.sized_int(i[0], size=(type_struct.size * 8))] except: print('{prop}: size ({len}) error for type {fmt}'.format(prop=p.name, len=len(p), fmt=fmt), file=sys.stderr) if len(p) == 4: type_struct = type_format['uint32'] elif len(p) == 2: type_struct = type_format['uint16'] elif len(p) == 1: type_struct = type_format['uint8'] else: return data for i in type_struct.iter_unpack(data): val_int += [dtschema.sized_int(i[0], size=(type_struct.size * 8))] if 'matrix' in fmt or 'phandle-array' in fmt: dim = dtschema.property_get_type_dim(p.name) if dim: if max(dim[1]) and dim[1][0] == dim[1][1]: stride = dim[1][1] elif max(dim[0]) and dim[0][0] == dim[0][1]: stride, rem = divmod(len(val_int), dim[0][1]) if rem: stride = len(val_int) else: # If multiple dimensions, check if one and only one dimension fits stride = get_stride(len(val_int), dim[1]) #if stride == 0: # stride = get_stride(len(val_int), dim[0]) if stride == 0: stride = len(val_int) #print(p.name, dim, stride) return [val_int[i:i+stride] for i in range(0, len(val_int), stride)] return [val_int] def node_props(fdt, nodename, offset): props_dict = {} poffset = fdt.first_property_offset(offset, QUIET_NOTFOUND) while poffset >= 0: p = fdt.get_property_by_offset(poffset) props_dict[p.name] = prop_value(nodename, p) poffset = fdt.next_property_offset(poffset, QUIET_NOTFOUND) return props_dict phandles = {} phandle_loc = [] def process_fixups(fdt, nodename, offset): if nodename != '__fixups__': return props = node_props(fdt, nodename, offset) global phandle_loc phandle_loc += [s for l in props.values() for s in l] def process_local_fixups(fdt, nodename, path, offset): global phandle_loc if nodename: path += '/' + nodename poffset = fdt.first_property_offset(offset, QUIET_NOTFOUND) while poffset >= 0: p = fdt.get_property_by_offset(poffset) for i in type_format['uint32'].iter_unpack(bytes(p)): phandle_loc += [path + ':' + p.name + ':' + str(i[0])] poffset = fdt.next_property_offset(poffset, QUIET_NOTFOUND) offset = fdt.first_subnode(offset, QUIET_NOTFOUND) while offset >= 0: nodename = fdt.get_name(offset) process_local_fixups(fdt, nodename, path, offset) offset = fdt.next_subnode(offset, QUIET_NOTFOUND) def fdt_scan_node(fdt, nodename, offset): if nodename == '__fixups__': process_fixups(fdt, nodename, offset) return if nodename == '__local_fixups__': process_local_fixups(fdt, '', '', offset) return if nodename.startswith('__'): return node_dict = node_props(fdt, nodename, offset) if 'phandle' in node_dict: #print('phandle', node_dict['phandle']) phandles[node_dict['phandle'][0][0]] = node_dict offset = fdt.first_subnode(offset, QUIET_NOTFOUND) while offset >= 0: nodename = fdt.get_name(offset) node = fdt_scan_node(fdt, nodename, offset) if node is not None: node_dict[nodename] = node offset = fdt.next_subnode(offset, QUIET_NOTFOUND) return node_dict phandle_args = { # phandle+args properties with fixed arg size or which don't match standard # 'foos' and '#foo-cells' pattern 'assigned-clocks': '#clock-cells', 'assigned-clock-parents': '#clock-cells', 'cooling-device': '#cooling-cells', 'interrupts-extended': '#interrupt-cells', 'interconnects': '#interconnect-cells', 'mboxes': '#mbox-cells', 'sound-dai': '#sound-dai-cells', 'msi-parent': '#msi-cells', 'gpio-ranges': 3, 'nvmem-cells': None, 'memory-region': None, } def _get_cells_size(node, cellname): if isinstance(cellname, int): return cellname elif cellname in node: return node[cellname][0][0] else: return 0 def _check_is_phandle(prop_path, cell): path = prop_path + ':' + str(cell * 4) return path in phandle_loc def _get_phandle_arg_size(prop_path, idx, cells, cellname): if not cells: return 0 phandle = cells[0] if phandle == 0 or not cellname: return 1 if phandle == 0xffffffff: # Use fixups data if available (examples) # Mixing unresolved and resolved phandles doesn't work if _check_is_phandle(prop_path, idx): cell_count = 1 while (cell_count < len(cells)) and not _check_is_phandle(prop_path, idx + cell_count): cell_count += 1 return cell_count else: return 0 if phandle not in phandles: return 0 node = phandles[phandle] return _get_cells_size(node, cellname) + 1 def fixup_phandles(dt, path=''): for k, v in dt.items(): if isinstance(v, dict): fixup_phandles(v, path=path + '/' + k) continue elif not {'phandle-array'} & set(dtschema.property_get_type(k)): continue elif not isinstance(v, list) or (len(v) > 1 or not isinstance(v[0], list)): # Not a matrix or already split, nothing to do continue elif k in phandle_args: cellname = phandle_args[k] elif k.endswith('s') and 'gpio' not in k: cellname = '#' + k[:-1] + '-cells' #print(k, v) i = _get_phandle_arg_size(path + ':' + k, 0, v[0], cellname) if i == 0: continue else: continue i = 0 dt[k] = [] val = v[0] #print(k, v) while i < len(val): #print(k, v, file=sys.stderr) cells = _get_phandle_arg_size(path + ':' + k, i, val[i:], cellname) if cells == 0: #print(k, v) break # Special case for interconnects which is pairs of phandles+args if k == 'interconnects': cells += _get_phandle_arg_size(path + ':' + k, i + cells, val[i + cells:], cellname) val[i] = dtschema.sized_int(val[i], phandle=True) dt[k] += [val[i:i + cells]] #print(k, dt[k], file=sys.stderr) i += cells def fixup_gpios(dt): if 'gpio-hog' in dt: return for k, v in dt.items(): if isinstance(v, dict): fixup_gpios(v) elif (k.endswith('-gpios') or k.endswith('-gpio') or k in {'gpio', 'gpios'}) and \ not k.endswith(',nr-gpios'): i = 0 dt[k] = [] val = v[0] while i < len(val): phandle = val[i] if phandle == 0: cells = 0 elif phandle == 0xffffffff: #print(val, file=sys.stderr) try: cells = val.index(0xffffffff, i + 1, -1) except: cells = len(val) #print(cells, file=sys.stderr) cells -= (i + 1) else: #print(k, v, file=sys.stderr) node = phandles[phandle] cells = _get_cells_size(node, '#gpio-cells') dt[k] += [val[i:i + cells + 1]] i += cells + 1 def fixup_interrupts(dt, icells): if 'interrupt-parent' in dt and isinstance(dt['interrupt-parent'], list): phandle = dt['interrupt-parent'][0][0] if phandle == 0xffffffff: del dt['interrupt-parent'] else: icells = _get_cells_size(phandles[phandle], '#interrupt-cells') for k, v in dt.items(): if isinstance(v, dict): if '#interrupt-cells' in dt: icells = _get_cells_size(dt, '#interrupt-cells') fixup_interrupts(v, icells) elif k == 'interrupts' and not isinstance(v, bytes): i = 0 dt[k] = [] val = v[0] while i < len(val): dt[k] += [val[i:i + icells]] i += icells elif k == 'interrupt-map' and not isinstance(v, bytes): icells = _get_cells_size(dt, '#interrupt-cells') ac = _get_cells_size(dt, '#address-cells') i = 0 dt[k] = [] val = v[0] phandle = val[ac + icells] if phandle == 0xffffffff: # Assume uniform sizes (same interrupt provider) try: cells = val.index(0xffffffff, ac + icells + 1) - (ac + icells) while i < len(val): dt[k] += [val[i:i + cells]] i += cells except: pass # Only 1 entry, nothing to do else: while i < len(val): p_icells = _get_cells_size(phandles[phandle], '#interrupt-cells') if '#address-cells' in phandles[phandle]: p_ac = _get_cells_size(phandles[phandle], '#address-cells') else: p_ac = 0 cells = ac + icells + 1 + p_ac + p_icells dt[k] += [val[i:i + cells]] i += cells def fixup_addresses(dt, ac, sc): for k, v in dt.items(): if isinstance(v, dict): if '#address-cells' in dt: ac = _get_cells_size(dt,'#address-cells') if '#size-cells' in dt: sc = _get_cells_size(dt, '#size-cells') fixup_addresses(v, ac, sc) elif k == 'reg': i = 0 dt[k] = [] val = v[0] while i < len(val): dt[k] += [val[i:i + ac + sc]] i += ac + sc elif k in {'ranges', 'dma-ranges'} and not isinstance(v, bool): child_cells = _get_cells_size(dt, '#address-cells') child_cells += _get_cells_size(dt, '#size-cells') i = 0 dt[k] = [] val = v[0] while i < len(val): dt[k] += [val[i:i + ac + child_cells]] i += ac + child_cells def fdt_unflatten(dtb): fdt = libfdt.Fdt(dtb) offset = fdt.first_subnode(-1, QUIET_NOTFOUND) dt = fdt_scan_node(fdt, '/', offset) #print(phandle_loc) fixup_gpios(dt) fixup_interrupts(dt, 1) fixup_addresses(dt, 2, 1) fixup_phandles(dt) # pprint.pprint(dt, compact=True) return dt dt-schema-2022.08.2/dtschema/lib.py000066400000000000000000001222361427720614200166170ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. # Python library for Devicetree schema validation import sys import os import glob import ruamel.yaml import re import pprint import copy import json import jsonschema from jsonschema.exceptions import RefResolutionError import dtschema.dtb schema_base_url = "http://devicetree.org/" schema_basedir = os.path.dirname(os.path.abspath(__file__)) # We use a lot of regex's in schema and exceeding the cache size has noticeable # peformance impact. re._MAXCACHE = 2048 class tagged_list(list): tags = {u'!u8': 8, u'!u16': 16, u'!u32': 32, u'!u64': 64} def __init__(self, int_list, tag, tags=tags): int_list = [sized_int(i, size=tags[tag]) for i in int_list] super().__init__(int_list) @staticmethod def constructor(loader, node): return tagged_list(loader.construct_sequence(node), node.tag) class sized_int(int): def __new__(cls, value, *args, **kwargs): return int.__new__(cls, value) def __init__(self, value, size=32, phandle=False): self.size = size self.phandle = phandle @staticmethod def constructor(loader, node): return sized_int(loader.construct_yaml_int(node), phandle=True) rtyaml = ruamel.yaml.YAML(typ='rt') rtyaml.allow_duplicate_keys = False rtyaml.preserve_quotes = True rtyaml.Constructor.add_constructor(u'!u8', tagged_list.constructor) rtyaml.Constructor.add_constructor(u'!u16', tagged_list.constructor) rtyaml.Constructor.add_constructor(u'!u32', tagged_list.constructor) rtyaml.Constructor.add_constructor(u'!u64', tagged_list.constructor) rtyaml.Constructor.add_constructor(u'!phandle', sized_int.constructor) yaml = ruamel.yaml.YAML(typ='safe') yaml.allow_duplicate_keys = False yaml.Constructor.add_constructor(u'!u8', tagged_list.constructor) yaml.Constructor.add_constructor(u'!u16', tagged_list.constructor) yaml.Constructor.add_constructor(u'!u32', tagged_list.constructor) yaml.Constructor.add_constructor(u'!u64', tagged_list.constructor) yaml.Constructor.add_constructor(u'!phandle', sized_int.constructor) def path_to_obj(tree, path): for pc in path: tree = tree[pc] return tree def get_line_col(tree, path, obj=None): if isinstance(obj, ruamel.yaml.comments.CommentedBase): return obj.lc.line, obj.lc.col obj = path_to_obj(tree, path) if isinstance(obj, ruamel.yaml.comments.CommentedBase): return obj.lc.line, obj.lc.col if len(path) < 1: return -1, -1 obj = path_to_obj(tree, list(path)[:-1]) if isinstance(obj, ruamel.yaml.comments.CommentedBase): if path[-1] == '$nodename': return -1, -1 return obj.lc.key(path[-1]) return -1, -1 schema_user_paths = [] def add_schema_path(path): if os.path.isdir(path): schema_user_paths.append(os.path.abspath(path)) def check_id_path(filename, id): id = id.replace('http://devicetree.org/schemas/', '') id = id.replace('#', '') base = os.path.abspath(filename) for p in schema_user_paths: base = base.replace(p + '/', '') base = base.replace(os.path.join(schema_basedir, 'schemas/'), '') base = base.replace(os.path.abspath('schemas/') + '/', '') if not id == base: print(filename + ": $id: relative path/filename doesn't match actual path or filename\n\texpected: http://devicetree.org/schemas/" + base + '#', file=sys.stderr) def do_load(filename): with open(filename, 'r', encoding='utf-8') as f: if filename.endswith('.json'): return json.load(f) return yaml.load(f.read()) def load_schema(schema): for path in schema_user_paths: if schema.startswith('schemas/'): schema_file = schema.partition('/')[2] else: schema_file = schema schema_file = os.path.join(path, schema_file) if not os.path.isfile(schema_file): continue return do_load(schema_file) return do_load(os.path.join(schema_basedir, schema)) def _value_is_type(subschema, key, type): if key not in subschema: return False if isinstance(subschema[key], list): val = subschema[key][0] else: val = subschema[key] return isinstance(val, type) def _is_int_schema(subschema): for match in ['const', 'enum', 'minimum', 'maximum']: if _value_is_type(subschema, match, int): return True return False def _is_string_schema(subschema): for match in ['const', 'enum', 'pattern']: if _value_is_type(subschema, match, str): return True return False def _extract_single_schemas(subschema): return {k: subschema.pop(k) for k in ('const', 'enum', 'pattern', 'minimum', 'maximum') if k in subschema} def _fixup_string_to_array(propname, subschema): # nothing to do if we don't have a set of string schema if not _is_string_schema(subschema): return subschema['items'] = [_extract_single_schemas(subschema)] def _fixup_reg_schema(propname, subschema): # nothing to do if we don't have a set of string schema if propname != 'reg': return if 'items' in subschema: if isinstance(subschema['items'], list): item_schema = subschema['items'][0] else: item_schema = subschema['items'] if not _is_int_schema(item_schema): return elif _is_int_schema(subschema): item_schema = subschema else: return subschema['items'] = [ {'items': [ _extract_single_schemas(item_schema) ] } ] def _is_matrix_schema(subschema): if 'items' not in subschema: return False if isinstance(subschema['items'], list): for l in subschema['items']: if l.keys() & {'items', 'maxItems', 'minItems'}: return True elif subschema['items'].keys() & {'items', 'maxItems', 'minItems'}: return True return False known_variable_matrix_props = { 'fsl,pins', } # If we have a matrix with variable inner and outer dimensions, then drop the dimensions # because we have no way to reconstruct them. def _fixup_int_matrix(propname, subschema): if not _is_matrix_schema(subschema): return outer_dim = _get_array_range(subschema) inner_dim = _get_array_range(subschema.get('items', {})) if propname in known_variable_matrix_props or \ (outer_dim[0] != outer_dim[1] and inner_dim[0] != inner_dim[1]): subschema.pop('items', None) subschema.pop('maxItems', None) subschema.pop('minItems', None) subschema['type'] = 'array' int_array_re = re.compile('int(8|16|32|64)-array') unit_types_re = re.compile('-(kBps|bits|percent|bp|m?hz|sec|ms|us|ns|ps|mm|nanoamp|(micro-)?ohms|micro(amp|watt)(-hours)?|milliwatt|microvolt|picofarads|(milli)?celsius|kelvin|kpascal)$') # Remove this once we remove array to matrix fixups known_array_props = { 'assigned-clock-rates', 'linux,keycodes', 'max8997,pmic-buck1-dvs-voltage', 'max8997,pmic-buck2-dvs-voltage', 'max8997,pmic-buck5-dvs-voltage', } def is_int_array_schema(propname, subschema): if 'allOf' in subschema: # Find 'items'. It may be under the 'allOf' or at the same level for item in subschema['allOf']: if 'items' in item: subschema = item continue if '$ref' in item: return int_array_re.search(item['$ref']) if '$ref' in subschema: return int_array_re.search(subschema['$ref']) elif unit_types_re.search(propname) or propname in known_array_props: return True return 'items' in subschema and \ ((isinstance(subschema['items'], list) and _is_int_schema(subschema['items'][0])) or (isinstance(subschema['items'], dict) and _is_int_schema(subschema['items']))) # Fixup an int array that only defines the number of items. # In this case, we allow either form [[ 0, 1, 2]] or [[0], [1], [2]] def _fixup_int_array_min_max_to_matrix(propname, subschema): if not is_int_array_schema(propname, subschema): return if 'allOf' in subschema: # Find 'min/maxItems'. It may be under the 'allOf' or at the same level for item in subschema['allOf']: if item.keys() & {'minItems', 'maxItems'}: subschema = item break if 'items' in subschema and isinstance(subschema['items'], list): return if _is_matrix_schema(subschema): return if subschema.get('maxItems') == 1: return tmpsch = {} if 'minItems' in subschema: tmpsch['minItems'] = subschema.pop('minItems') if 'maxItems' in subschema: tmpsch['maxItems'] = subschema.pop('maxItems') if tmpsch: subschema['oneOf'] = [copy.deepcopy(tmpsch), {'items': [copy.deepcopy(tmpsch)]}] subschema['oneOf'][0].update({'items': {'maxItems': 1}}) # if minItems can be 1, then both oneOf clauses can be true so increment # minItems in one clause to prevent that. if subschema['oneOf'][0].get('minItems') == 1: subschema['oneOf'][0]['minItems'] += 1 # Since we added an 'oneOf' the tree walking code won't find it and we need to do fixups _fixup_items_size(subschema['oneOf']) def _fixup_remove_empty_items(subschema): if 'items' not in subschema: return elif isinstance(subschema['items'], dict): _fixup_remove_empty_items(subschema['items']) return for item in subschema['items']: item.pop('description', None) _fixup_remove_empty_items(item) if item != {}: break else: subschema.setdefault('type', 'array') subschema.setdefault('maxItems', len(subschema['items'])) subschema.setdefault('minItems', len(subschema['items'])) del subschema['items'] def _fixup_int_array_items_to_matrix(propname, subschema): itemkeys = ('items', 'minItems', 'maxItems', 'uniqueItems', 'default') if not is_int_array_schema(propname, subschema): return if 'allOf' in subschema: # Find 'items'. It may be under the 'allOf' or at the same level for item in subschema['allOf']: if 'items' in item: subschema = item break if 'items' not in subschema or _is_matrix_schema(subschema): return if isinstance(subschema['items'], dict): subschema['items'] = {k: subschema.pop(k) for k in itemkeys if k in subschema} if isinstance(subschema['items'], list): subschema['items'] = [{k: subschema.pop(k) for k in itemkeys if k in subschema}] def _fixup_scalar_to_array(propname, subschema): if not _is_int_schema(subschema): return subschema['items'] = [{'items': [_extract_single_schemas(subschema)]}] def _fixup_items_size(schema): # Make items list fixed size-spec if isinstance(schema, list): for l in schema: _fixup_items_size(l) elif isinstance(schema, dict): schema.pop('description', None) if 'items' in schema: schema['type'] = 'array' if isinstance(schema['items'], list): c = len(schema['items']) if 'minItems' not in schema: schema['minItems'] = c if 'maxItems' not in schema: schema['maxItems'] = c _fixup_items_size(schema['items']) elif 'maxItems' in schema and 'minItems' not in schema: schema['minItems'] = schema['maxItems'] elif 'minItems' in schema and 'maxItems' not in schema: schema['maxItems'] = schema['minItems'] def fixup_schema_to_201909(schema): if not isinstance(schema, dict): return # dependencies is now split into dependentRequired and dependentSchema try: val = schema.pop('dependencies') for k, v in val.items(): if isinstance(v, list): schema.setdefault('dependentRequired', {}) schema['dependentRequired'][k] = v else: schema.setdefault('dependentSchemas', {}) schema['dependentSchemas'][k] = v except: pass def fixup_schema_to_202012(schema): if not isinstance(schema, dict): return fixup_schema_to_201909(schema) try: if isinstance(schema['items'], list): schema['prefixItems'] = schema.pop('items') for i in schema['prefixItems']: fixup_schema_to_202012(i) if isinstance(schema['items'], dict): fixup_schema_to_202012(schema['items']) except: pass try: val = schema.pop('additionalItems') schema['unevaluatedItems'] = val except: pass def fixup_vals(propname, schema): # Now we should be a the schema level to do actual fixups #print(schema) schema.pop('description', None) _fixup_reg_schema(propname, schema) _fixup_remove_empty_items(schema) _fixup_int_matrix(propname, schema) _fixup_int_array_min_max_to_matrix(propname, schema) _fixup_int_array_items_to_matrix(propname, schema) _fixup_string_to_array(propname, schema) _fixup_scalar_to_array(propname, schema) _fixup_items_size(schema) fixup_schema_to_201909(schema) def walk_properties(propname, schema): if not isinstance(schema, dict): return # Recurse until we don't hit a conditional # Note we expect to encounter conditionals first. # For example, a conditional below 'items' is not supported for cond in ['allOf', 'oneOf', 'anyOf']: if cond in schema.keys(): for l in schema[cond]: walk_properties(propname, l) if 'then' in schema.keys(): walk_properties(propname, schema['then']) fixup_vals(propname, schema) def fixup_schema(schema): # Remove parts not necessary for validation schema.pop('examples', None) schema.pop('maintainers', None) schema.pop('historical', None) add_select_schema(schema) fixup_sub_schema(schema, True) def fixup_sub_schema(schema, is_prop): if not isinstance(schema, dict): return schema.pop('description', None) fixup_interrupts(schema) if is_prop: fixup_node_props(schema) # 'additionalProperties: true' doesn't work with 'unevaluatedProperties', so # remove it. It's in the schemas for common (incomplete) schemas. if 'additionalProperties' in schema and schema['additionalProperties'] == True: schema.pop('additionalProperties', None) for k, v in schema.items(): if k in ['select', 'if', 'then', 'else', 'additionalProperties', 'not']: fixup_sub_schema(v, False) if k in ['allOf', 'anyOf', 'oneOf']: for subschema in v: fixup_sub_schema(subschema, True) if k not in ['dependentRequired', 'dependentSchemas', 'dependencies', 'properties', 'patternProperties', '$defs']: continue for prop in v: walk_properties(prop, v[prop]) # Recurse to check for {properties,patternProperties} in each prop fixup_sub_schema(v[prop], True) fixup_schema_to_201909(schema) def fixup_node_props(schema): if not {'properties', 'patternProperties', 'unevaluatedProperties'} & schema.keys(): return if ('additionalProperties' in schema and schema['additionalProperties'] is True) or \ ('unevaluatedProperties' in schema and schema['unevaluatedProperties'] is True): return schema.setdefault('properties', dict()) schema['properties'].setdefault('phandle', True) schema['properties'].setdefault('status', True) schema['properties'].setdefault('secure-status', True) schema['properties'].setdefault('$nodename', True) keys = list() if 'properties' in schema: keys.extend(schema['properties']) if 'patternProperties' in schema: keys.extend(schema['patternProperties']) for key in keys: if re.match(r'^pinctrl-[0-9]', key): break else: schema['properties'].setdefault('pinctrl-names', True) schema.setdefault('patternProperties', dict()) schema['patternProperties']['pinctrl-[0-9]+'] = True if "clocks" in keys and "assigned-clocks" not in keys: schema['properties']['assigned-clocks'] = True schema['properties']['assigned-clock-rates'] = True schema['properties']['assigned-clock-parents'] = True def extract_node_compatibles(schema): if not isinstance(schema, dict): return set() compatible_list = set() for l in item_generator(schema, 'enum'): if isinstance(l[0], str): compatible_list.update(l) for l in item_generator(schema, 'const'): compatible_list.update([str(l)]) for l in item_generator(schema, 'pattern'): compatible_list.update([l]) return compatible_list def extract_compatibles(schema): if not isinstance(schema, dict): return set() compatible_list = set() for sch in item_generator(schema, 'compatible'): compatible_list.update(extract_node_compatibles(sch)) return compatible_list def item_generator(json_input, lookup_key): if isinstance(json_input, dict): for k, v in json_input.items(): if k == lookup_key: yield v else: for child_val in item_generator(v, lookup_key): yield child_val elif isinstance(json_input, list): for item in json_input: for item_val in item_generator(item, lookup_key): yield item_val # Convert to standard types from ruamel's CommentedMap/Seq def convert_to_dict(schema): if isinstance(schema, dict): result = {} for k, v in schema.items(): result[k] = convert_to_dict(v) elif isinstance(schema, list): result = [] for item in schema: result.append(convert_to_dict(item)) else: result = schema return result def add_select_schema(schema): '''Get a schema to be used in select tests. If the provided schema has a 'select' property, then use that as the select schema. If it has a compatible property, then create a select schema from that. If it has a $nodename property, then create a select schema from that. If it has none of those, then return a match-nothing schema ''' if "select" in schema: return if 'properties' not in schema: schema['select'] = False return if 'compatible' in schema['properties']: compatible_list = extract_node_compatibles(schema['properties']['compatible']) if len(compatible_list): try: compatible_list.remove('syscon') except: pass try: compatible_list.remove('simple-mfd') except: pass if len(compatible_list) != 0: schema['select'] = { 'required': ['compatible'], 'properties': {'compatible': {'contains': {'enum': sorted(compatible_list)}}}} return if '$nodename' in schema['properties'] and schema['properties']['$nodename'] is not True: schema['select'] = { 'required': ['$nodename'], 'properties': {'$nodename': convert_to_dict(schema['properties']['$nodename'])}} return schema['select'] = False def fixup_interrupts(schema): # Supporting 'interrupts' implies 'interrupts-extended' is also supported. if 'properties' not in schema: return # Any node with 'interrupts' can have 'interrupt-parent' if schema['properties'].keys() & {'interrupts', 'interrupt-controller'} and \ 'interrupt-parent' not in schema['properties']: schema['properties']['interrupt-parent'] = True if 'interrupts' not in schema['properties'] or 'interrupts-extended' in schema['properties']: return schema['properties']['interrupts-extended'] = copy.deepcopy(schema['properties']['interrupts']) if not ('required' in schema and 'interrupts' in schema['required']): return # Currently no better way to express either 'interrupts' or 'interrupts-extended' # is required. If this fails validation, the error reporting is the whole # schema file fails validation reqlist = [{'required': ['interrupts']}, {'required': ['interrupts-extended']}] if 'oneOf' in schema: if 'allOf' not in schema: schema['allOf'] = [] schema['allOf'].append({'oneOf': reqlist}) else: schema['oneOf'] = reqlist schema['required'].remove('interrupts') def make_compatible_schema(schemas): compat_sch = [{'enum': []}] compatible_list = set() for sch in schemas.values(): compatible_list |= extract_compatibles(sch) # Allow 'foo' values for examples compat_sch += [{'pattern': '^foo'}] prog = re.compile('.*[\^\[{\(\$].*') for c in compatible_list: if prog.match(c): # Exclude the generic pattern if c != '^[a-zA-Z0-9][a-zA-Z0-9,+\-._]+$': compat_sch += [{'pattern': c}] else: compat_sch[0]['enum'].append(c) compat_sch[0]['enum'].sort() schemas['generated-compatibles'] = { '$id': 'generated-compatibles', '$filename': 'Generated schema of documented compatible strings', 'select': True, 'properties': { 'compatible': { 'items': { 'anyOf': compat_sch } } } } def get_undocumented_compatibles(compatible_list): global schema_cache undoc_compats = [] validator = dtschema.DTValidator(schema_cache['generated-compatibles']) for compat in compatible_list: if not validator.is_valid({"compatible": [ compat ]}): undoc_compats += [ compat ] return undoc_compats def process_schema(filename): try: schema = load_schema(filename) except: print(filename + ": ignoring, error parsing file", file=sys.stderr) return # Check that the validation schema is valid try: DTValidator.check_schema(schema) except jsonschema.SchemaError as exc: print(filename + ": ignoring, error in schema: " + ': '.join(str(x) for x in exc.path), file=sys.stderr) #print(exc.message) return except: print(filename + ": ignoring, unknown error in schema (not a schema?)", file=sys.stderr) return if 'select' not in schema: print(filename + ": warning: no 'select' found in schema found", file=sys.stderr) return schema["type"] = "object" schema["$filename"] = filename return schema def process_schemas(schema_paths, core_schema=True): schemas = {} for filename in schema_paths: if not os.path.isfile(filename): continue sch = process_schema(os.path.abspath(filename)) if not sch: continue if sch['$id'] in schemas: print(os.path.abspath(filename) + ": duplicate '$id' value '" + sch['$id'] + "'", file=sys.stderr) else: schemas[sch['$id']] = sch if core_schema: schema_paths.append(os.path.join(schema_basedir, 'schemas/')) for path in schema_paths: count = 0 if not os.path.isdir(path): continue for filename in glob.iglob(os.path.join(os.path.abspath(path), "**/*.yaml"), recursive=True): sch = process_schema(os.path.abspath(filename)) if sch: count += 1 if sch['$id'] in schemas: print(os.path.abspath(filename) + ": duplicate '$id' value '" + sch['$id'] + "'", file=sys.stderr) else: schemas[sch['$id']] = sch if count == 0: print("warning: no schema found in path: %s" % path, file=sys.stderr) make_compatible_schema(schemas) return schemas def _get_array_range(subschema): if isinstance(subschema, list): if len(subschema) != 1: return (0, 0) subschema = subschema[0] if 'items' in subschema and isinstance(subschema['items'], list): max = len(subschema['items']) min = subschema.get('minItems', max) else: min = subschema.get('minItems', 1) max = subschema.get('maxItems', subschema.get('minItems', 0)) return (min, max) def _merge_dim(dim1, dim2): d = [] for i in range(0, 2): if dim1[i] == (0, 0): d.insert(i, dim2[i]) elif dim2[i] == (0, 0): d.insert(i, dim1[i]) else: d.insert(i, (min(dim1[i] + dim2[i]), max(dim1[i] + dim2[i]))) return tuple(d) type_re = re.compile('(flag|u?int(8|16|32|64)(-(array|matrix))?|string(-array)?|phandle(-array)?)') def _extract_prop_type(props, schema, propname, subschema, is_pattern): if not isinstance(subschema, dict): return if propname.startswith('$'): return props.setdefault(propname, []) if subschema.keys() & {'properties', 'patternProperties', 'additionalProperties'}: _extract_subschema_types(props, schema, subschema) # We only support local refs if propname not in props and '$ref' in subschema and subschema['$ref'].startswith('#/'): sch_path = subschema['$ref'].split('/')[1:] subschema = schema for p in sch_path: subschema = subschema[p] #print(propname, sch_path, subschema, file=sys.stderr) _extract_prop_type(props, schema, propname, subschema, is_pattern) for k in subschema.keys() & {'allOf', 'oneOf', 'anyOf'}: for v in subschema[k]: _extract_prop_type(props, schema, propname, v, is_pattern) new_prop = {} prop_type = None if 'type' in subschema and subschema['type'] == 'object': prop_type = 'node' else: try: prop_type = type_re.search(subschema['$ref']).group(0) except: if 'type' in subschema and subschema['type'] == 'boolean': prop_type = 'flag' elif 'items' in subschema: items = subschema['items'] if (isinstance(items, list) and _is_string_schema(items[0])) or \ (isinstance(items, dict) and _is_string_schema(items)): # implicit string type prop_type = 'string-array' elif not (isinstance(items, list) and len(items) == 1 and \ 'items' in items and isinstance(items['items'], list) and len(items['items']) == 1) and \ unit_types_re.search(propname): prop_type = 'uint32-matrix' else: prop_type = None elif '$ref' in subschema and re.search(r'\.yaml#?$', subschema['$ref']): prop_type = 'node' else: prop_type = None new_prop['type'] = prop_type new_prop['$id'] = [schema['$id']] if is_pattern: new_prop['regex'] = re.compile(propname) if not prop_type: if len(props[propname]) == 0: props[propname] += [new_prop] return # handle matrix dimensions if prop_type == 'phandle-array' or prop_type.endswith('-matrix'): dim = (_get_array_range(subschema), _get_array_range(subschema.get('items', {}))) new_prop['dim'] = dim else: dim = ((0, 0), (0, 0)) if propname in props: dup_prop = None for p in props[propname]: if p['type'] is None: dup_prop = p break if dim != ((0, 0), (0, 0)) and (p['type'] == 'phandle-array' or p['type'].endswith('-matrix')): if not 'dim' in p: p['dim'] = dim elif p['dim'] != dim: # Conflicting dimensions p['dim'] = _merge_dim(p['dim'], dim) return if p['type'].startswith(prop_type): # Already have the same or looser type if schema['$id'] not in p['$id']: p['$id'] += [schema['$id']] return elif p['type'] in prop_type: # Replace scalar type with array type new_prop['$id'] += p['$id'] dup_prop = p break if dup_prop: props[propname].remove(dup_prop) props[propname] += [new_prop] def _extract_subschema_types(props, schema, subschema): if not isinstance(subschema, dict): return if 'additionalProperties' in subschema: _extract_subschema_types(props, schema, subschema['additionalProperties']) for k in subschema.keys() & {'properties', 'patternProperties'}: if isinstance(subschema[k], dict): for p,v in subschema[k].items(): _extract_prop_type(props, schema, p, v, k == 'patternProperties') def extract_types(): global schema_cache props = {} for sch in schema_cache.values(): _extract_subschema_types(props, sch, sch) return props def get_prop_types(want_missing_types=False, want_node_types=False): pat_props = {} props = dtschema.extract_types() # hack to remove aliases and generic patterns del props['^[a-z][a-z0-9\-]*$'] props.pop('^[a-zA-Z][a-zA-Z0-9\\-_]{0,63}$', None) props.pop('^.*$', None) props.pop('.*', None) # Remove node types if not want_node_types: for val in props.values(): val[:] = [t for t in val if t['type'] != 'node'] # Remove all properties without a type if not want_missing_types: for val in props.values(): val[:] = [t for t in val if t['type'] is not None] # Delete any entries now empty due to above operations for key in [key for key in props if len(props[key]) == 0]: del props[key] # Split out pattern properties for key in [key for key in props if len(props[key]) and 'regex' in props[key][0] ]: # Only want patternProperties with type and some amount of fixed string if re.search(r'[0-9a-zA-F-]{3}', key): #print(key, props[key], file=sys.stderr) pat_props[key] = props[key] del props[key] return [ props, pat_props ] props = None pat_props = None def property_get_type(propname): global props global pat_props if not props: props, pat_props = get_prop_types() type = [] if propname in props: for v in props[propname]: if v['type']: type += [v['type']] if len(type) == 0: for v in pat_props.values(): if v[0]['type'] and v[0]['type'] not in type and v[0]['regex'].search(propname): type += [v[0]['type']] # Don't return 'node' as a type if there's other types if len(type) > 1 and 'node' in type: type.remove('node') return type def property_get_type_dim(propname): global props global pat_props if not props: props, pat_props = get_prop_types() if propname in props: for v in props[propname]: if 'dim' in v: return v['dim'] for v in pat_props.values(): if v[0]['type'] and 'dim' in v[0] and v[0]['regex'].search(propname): return v[0]['dim'] return None def load(filename, line_number=False): if filename.endswith('.dtb'): with open(filename, 'rb') as f: return [ dtschema.dtb.fdt_unflatten(f.read()) ] with open(filename, 'r', encoding='utf-8') as f: if line_number: return rtyaml.load(f.read()) else: return yaml.load(f.read()) def make_property_type_cache(): global schema_cache props, pat_props = get_prop_types() for val in props.values(): val[:] = [t for t in val if 'regex' not in t] for t in val: del t['$id'] schema_cache['generated-types'] = { '$id': 'generated-types', '$filename': 'Generated property types', 'select': False, 'properties': {k: props[k] for k in sorted(props)} } for val in pat_props.values(): for t in val: t.pop('regex', None) del t['$id'] schema_cache['generated-pattern-types'] = { '$id': 'generated-pattern-types', '$filename': 'Generated property types', 'select': False, 'properties': {k: pat_props[k] for k in sorted(pat_props)} } schema_cache = {} def set_schemas(schema_files, core_schema=True): global schema_cache, pat_props, props if len(schema_files) == 1 and os.path.isfile(schema_files[0]): # a processed schema file schema_cache = dtschema.load_schema(os.path.abspath(schema_files[0])) # Convert old format to new if isinstance(schema_cache, list): d = {} for sch in schema_cache: d[sch['$id']] = sch schema_cache = d if 'generated-types' in schema_cache: props = schema_cache['generated-types']['properties'] if 'generated-pattern-types' in schema_cache: pat_props = schema_cache['generated-pattern-types']['properties'] for k in pat_props: pat_props[k][0]['regex'] = re.compile(k) else: schema_cache = process_schemas(schema_files, core_schema) make_property_type_cache() return schema_cache def http_handler(uri): global schema_cache '''Custom handler for http://devicetre.org YAML references''' try: if schema_base_url in uri: my_uri = uri + '#' if my_uri in schema_cache: return schema_cache[my_uri] # If we have a schema_cache, then the schema should have been there unless the schema had errors if len(schema_cache): return False if 'meta-schemas' in uri: return load_schema(uri.replace(schema_base_url, '')) try: schema = load_schema(uri.replace(schema_base_url, '')) except Exception as exc: raise RefResolutionError('Unable to find schema file matching $id: ' + uri) try: DTValidator.check_schema(schema) except Exception as exc: raise RefResolutionError('Error in referenced schema matching $id: ' + uri) return schema from urllib.request import urlopen return yaml.load(urlopen(uri).read().decode('utf-8')) except FileNotFoundError as e: print('Unknown file referenced:', e, file=sys.stderr) exit(-1) handlers = {"http": http_handler} def typeSize(validator, typeSize, instance, schema): if not isinstance(instance[0], list): return if isinstance(instance[0][0], sized_int): size = instance[0][0].size else: size = 32 if typeSize != size: yield jsonschema.ValidationError("size is %r, expected %r" % (size, typeSize)) DTVal = jsonschema.validators.extend(jsonschema.Draft201909Validator, {'typeSize': typeSize}) class DTValidator(DTVal): '''Custom Validator for Devicetree Schemas Overrides the Draft7 metaschema with the devicetree metaschema. This validator is used in exactly the same way as the Draft7Validator. Schema files can be validated with the .check_schema() method, and .validate() will check the data in a devicetree file. ''' resolver = jsonschema.RefResolver('', None, handlers=handlers) format_checker = jsonschema.FormatChecker() def __init__(self, *args, **kwargs): kwargs.setdefault('resolver', self.resolver) kwargs.setdefault('format_checker', self.format_checker) super().__init__(*args, **kwargs) @classmethod def annotate_error(self, error, schema, path): error.note = None error.schema_file = None for e in error.context: self.annotate_error(e, schema, path + e.schema_path) scope = self.ID_OF(schema) self.resolver.push_scope(scope) ref_depth = 1 lastp = '' for p in path: # json-schema 3.2.0 includes 'if' in schema path if lastp != 'properties' and p == 'if': continue lastp = p while '$ref' in schema and isinstance(schema['$ref'], str): ref = self.resolver.resolve(schema['$ref']) schema = ref[1] self.resolver.push_scope(ref[0]) ref_depth += 1 if '$id' in schema and isinstance(schema['$id'], str): error.schema_file = schema['$id'] schema = schema[p] if isinstance(schema, dict): if 'description' in schema and isinstance(schema['description'], str): error.note = schema['description'] while ref_depth > 0: self.resolver.pop_scope() ref_depth -= 1 if isinstance(error.schema, dict) and 'description' in error.schema: error.note = error.schema['description'] @classmethod def iter_schema_errors(cls, schema): meta_schema = cls.resolver.resolve_from_url(schema['$schema']) for error in cls(meta_schema).iter_errors(schema): cls(meta_schema).annotate_error(error, meta_schema, error.schema_path) error.linecol = get_line_col(schema, error.path) yield error def iter_errors(self, instance, _schema=None): for error in super().iter_errors(instance, _schema): error.linecol = get_line_col(instance, error.path) error.note = None error.schema_file = None yield error @classmethod def check_schema(cls, schema): meta_schema = cls.resolver.resolve_from_url(schema['$schema']) for error in cls(meta_schema).iter_errors(schema): raise jsonschema.SchemaError.create_from(error) fixup_schema(schema) @classmethod def _check_schema_refs(self, schema): if isinstance(schema, dict) and '$ref' in schema: self.resolver.resolve(schema['$ref']) elif isinstance(schema, dict): for k, v in schema.items(): self._check_schema_refs(v) elif isinstance(schema, (list, tuple)): for i in range(len(schema)): self._check_schema_refs(schema[i]) @classmethod def check_schema_refs(self, filename, schema): scope = self.ID_OF(schema) if scope: self.resolver.push_scope(scope) try: self._check_schema_refs(schema) except jsonschema.RefResolutionError as exc: print(filename + ':', exc, file=sys.stderr) check_id_path(filename, schema['$id']) @classmethod def _check_str(self, err_msg, schema, key, v): if not (isinstance(v, ruamel.yaml.scalarstring.SingleQuotedScalarString) or isinstance(v, ruamel.yaml.scalarstring.DoubleQuotedScalarString)): return # Only checking const and list values if key and key != 'const': return if v[0] in '#/"': return # Flow style with ',' needs quoting if schema.fa.flow_style() and ',' in v: return if isinstance(schema, ruamel.yaml.comments.CommentedBase): if isinstance(schema, dict): line = schema.lc.key(key)[0] else: line = schema.lc.line line += 1 else: line = None print(err_msg + str(line) + ": quotes are not necessary: " + v, file=sys.stderr) @classmethod def check_quotes(self, err_msg, schema): if isinstance(schema, dict): for k, v in schema.items(): self._check_str(err_msg, schema, k, v) self.check_quotes(err_msg, v) if isinstance(schema, list): for s in schema: self._check_str(err_msg, schema, None, s) self.check_quotes(err_msg, s) def format_error(filename, error, prefix="", nodename=None, verbose=False): src = prefix + os.path.abspath(filename) + ':' if error.linecol[0] >= 0: src = src + '%i:%i: ' % (error.linecol[0]+1, error.linecol[1]+1) else: src += ' ' if nodename is not None: src += nodename + ': ' if error.absolute_path: for path in error.absolute_path: src += str(path) + ":" src += ' ' #print(error.__dict__) if verbose: msg = str(error) elif error.context: # An error on a conditional will have context with sub-errors msg = "'" + error.schema_path[-1] + "' conditional failed, one must be fixed:" for suberror in sorted(error.context, key=lambda e: e.path): if suberror.context: msg += '\n' + format_error(filename, suberror, prefix=prefix+"\t", nodename=nodename, verbose=verbose) elif suberror.message not in msg: msg += '\n' + prefix + '\t' + suberror.message if suberror.note and suberror.note != error.note: msg += '\n\t\t' + prefix + 'hint: ' + suberror.note elif error.schema_path[-1] == 'oneOf': msg = 'More than one condition true in oneOf schema:\n\t' + \ '\t'.join(pprint.pformat(error.schema, width=72).splitlines(True)) else: msg = error.message if error.note: msg += '\n\t' + prefix + 'hint: ' + error.note if error.schema_file: msg += '\n\t' + prefix + 'from schema $id: ' + error.schema_file return src + msg dt-schema-2022.08.2/dtschema/meta-schemas/000077500000000000000000000000001427720614200200405ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/meta-schemas/base.yaml000066400000000000000000000033611427720614200216410ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. %YAML 1.2 --- $id: "http://devicetree.org/meta-schemas/base.yaml#" $schema: "http://json-schema.org/draft/2019-09/schema" description: "Metaschema for devicetree binding documentation" allOf: - $ref: "http://json-schema.org/draft-07/schema#" - $ref: "http://devicetree.org/meta-schemas/keywords.yaml#" properties: # listing all properties here to narrow the scope of what is allowed in # devicetree schema files. This list can be relaxed in the future as we # become more comfortable with the validation vocabulary. # Also, being explicit about what properties are allowed helps to catch # misspelled or unsupported tests. $id: pattern: 'http://devicetree.org/schemas/.*\.yaml#' $schema: enum: - "http://devicetree.org/meta-schemas/core.yaml#" - "http://devicetree.org/meta-schemas/base.yaml#" title: maxLength: 100 examples: type: array items: type: string maintainers: type: array items: type: string format: email select: description: '"select" must contain a valid json-schema' allOf: - $ref: "http://json-schema.org/draft-07/schema#" - oneOf: - type: object properties: properties: true required: true - type: boolean propertyNames: enum: [ $id, $schema, title, description, examples, required, allOf, anyOf, oneOf, definitions, $defs, additionalProperties, dependencies, dependentRequired, dependentSchemas, patternProperties, properties, if, then, else, unevaluatedProperties, deprecated, maintainers, select, $ref ] required: - $id - $schema - title - maintainers dt-schema-2022.08.2/dtschema/meta-schemas/boolean.yaml000066400000000000000000000005231427720614200223430ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. %YAML 1.2 --- $id: "http://devicetree.org/meta-schemas/boolean.yaml#" $schema: "http://json-schema.org/draft/2019-09/schema#" properties: type: const: boolean description: {} default: {} deprecated: {} additionalProperties: false dt-schema-2022.08.2/dtschema/meta-schemas/cell.yaml000066400000000000000000000043011427720614200216410ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. %YAML 1.2 --- $id: "http://devicetree.org/meta-schemas/cell.yaml#" $schema: "http://json-schema.org/draft/2019-09/schema#" array: description: cell array properties must define how many entries and what the entries are when there is more than one entry. anyOf: - description: 'Only "maxItems" is required for a single entry if there are no constraints defined for the values.' properties: maxItems: const: 1 required: [maxItems] propertyNames: enum: [maxItems, description, deprecated] - description: Arrays must be described with a combination of minItems/maxItems/items properties: minItems: minimum: 1 maxItems: minimum: 2 oneOf: type: array items: $ref: '#/array' anyOf: type: array items: $ref: '#/array' items: description: '"items" can be a list defining each entry or a schema applying to all items. A list has an implicit size. A schema requires minItems/maxItems to define the size.' oneOf: - type: object allOf: - $ref: '#/array' - type: array items: $ref: '#/single' - type: array maxItems: 1 # for more than 1, outer 'items' should be a schema items: allOf: - $ref: '#/array' required: - items additionalItems: type: boolean const: true description: true deprecated: true additionalProperties: false - $ref: '#/single' single: description: A singular entry should be described with scalar constraints properties: description: true const: type: integer enum: items: type: integer minimum: {} maximum: {} default: type: integer oneOf: $ref: #/single propertyNames: enum: [ description, deprecated, const, enum, minimum, maximum, multipleOf, default, $ref, oneOf ] dt-schema-2022.08.2/dtschema/meta-schemas/clocks.yaml000066400000000000000000000016161427720614200222060ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. %YAML 1.2 --- $id: "http://devicetree.org/meta-schemas/clocks.yaml#" $schema: "http://json-schema.org/draft/2019-09/schema#" properties: clocks: oneOf: - $ref: "cell.yaml#/array" - $ref: "nodes.yaml" clock-ranges: $ref: "boolean.yaml" clock-indices: $ref: "cell.yaml#/array" assigned-clocks: $ref: "cell.yaml#/array" assigned-clock-parents: $ref: "cell.yaml#/array" assigned-clock-rates: $ref: "cell.yaml#/array" clock-frequency: $ref: "cell.yaml#/single" bus-frequency: $ref: "cell.yaml#/single" dependentRequired: clock-output-names: ['#clock-cells'] clock-indices: ['#clock-cells'] clock-names: [clocks] clock-ranges: [clocks] assigned-clocks: [clocks] assigned-clock-parents: [assigned-clocks] assigned-clock-rates: [assigned-clocks] dt-schema-2022.08.2/dtschema/meta-schemas/core.yaml000066400000000000000000000074321427720614200216620ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018-2019 Arm Ltd. %YAML 1.2 --- $id: "http://devicetree.org/meta-schemas/core.yaml#" $schema: "http://json-schema.org/draft/2019-09/schema#" description: "Metaschema for devicetree binding documentation" allOf: - $ref: "http://devicetree.org/meta-schemas/base.yaml#" - description: Either unevaluatedProperties or additionalProperties must be present oneOf: - required: [ unevaluatedProperties ] - required: [ additionalProperties ] definitions: all-properties: allOf: - $ref: "#/definitions/core-properties" - $ref: "clocks.yaml#" - $ref: "dma.yaml#" - $ref: "gpios.yaml#" - $ref: "hwlock.yaml#" - $ref: "iio.yaml#" - $ref: "interrupts.yaml#" - $ref: "iommu.yaml#" - $ref: "mailbox.yaml#" - $ref: "nvmem.yaml#" - $ref: "phy.yaml#" - $ref: "power-domain.yaml#" - $ref: "pwm.yaml#" - $ref: "reset.yaml#" - $ref: "mailbox.yaml#" - $ref: "vendor-props.yaml#" core-properties: properties: ranges: $ref: "cell.yaml#/array" reg: $ref: "cell.yaml#/array" compatible: $ref: "string-array.yaml" $nodename: $ref: "string-array.yaml" memory-region: $ref: "cell.yaml#/array" memory-region-names: $ref: "string-array.yaml" patternProperties: '.*-names$': $ref: "string-array.yaml" '^#.*-cells$': $ref: "cell.yaml#/single" '-supply$': propertyNames: enum: [ description, deprecated ] '-(bits|-kBps|percent|bp|mhz|hz|sec|ms|us|ns|ps|mm|microamp(-hours)?|(micro-)?ohms|microwatt-hours|microvolt|(femto|pico)farads|(milli)?celsius|kelvin|kpascal)$': allOf: - $ref: "cell.yaml#/array" - description: Standard unit suffix properties don't need a type $ref propertyNames: not: const: $ref '^.*$': properties: # 'boolean' and 'object' are the only native types allowed type: enum: [ boolean, object ] properties: $ref: "#/definitions/all-properties" patternProperties: $ref: "#/definitions/all-properties" $ref: pattern: '(#$|#\/)?' allOf: - if: type: object properties: type: const: object required: - type then: $ref: "nodes.yaml#" - if: required: [ properties ] then: description: node schemas must have a type or $ref anyOf: - required: [ type ] - required: [ $ref ] dependentRequired: "#size-cells": [ "#address-cells" ] memory-region-names: [ memory-region ] reg-names: [ reg ] properties: patternProperties: $ref: "#/definitions/all-properties" properties: $ref: "#/definitions/all-properties" allOf: items: properties: properties: $ref: "#/definitions/all-properties" patternProperties: $ref: "#/definitions/all-properties" anyOf: items: properties: properties: $ref: "#/definitions/all-properties" patternProperties: $ref: "#/definitions/all-properties" oneOf: items: properties: properties: $ref: "#/definitions/all-properties" patternProperties: $ref: "#/definitions/all-properties" if: properties: properties: $ref: "#/definitions/all-properties" patternProperties: $ref: "#/definitions/all-properties" anyOf: - required: - properties - required: - patternProperties dt-schema-2022.08.2/dtschema/meta-schemas/dma.yaml000066400000000000000000000004261427720614200214670ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2020 Arm Ltd. %YAML 1.2 --- $id: "http://devicetree.org/meta-schemas/dma.yaml#" $schema: "http://json-schema.org/draft/2019-09/schema#" properties: dmas: $ref: "cell.yaml#/array" dependentRequired: dma-names: [dmas] dt-schema-2022.08.2/dtschema/meta-schemas/gpios.yaml000066400000000000000000000012351427720614200220460ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. %YAML 1.2 --- $id: "http://devicetree.org/meta-schemas/gpios.yaml#" $schema: "http://json-schema.org/draft/2019-09/schema#" properties: gpio-controller: $ref: "boolean.yaml" gpio-line-names: $ref: "string-array.yaml" ngpios: $ref: "cell.yaml#/single" gpio-ranges: $ref: "cell.yaml#/array" gpios: $ref: "cell.yaml#/array" patternProperties: '(? dt-schema-2022.08.2/dtschema/schemas/bus/000077500000000000000000000000001427720614200177055ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/bus/qemu,platform.yaml000066400000000000000000000020701427720614200233600ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2022 Arm Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/bus/qemu,platform.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: QEMU Platform bus maintainers: - Rob Herring select: properties: compatible: contains: const: qemu,platform required: - compatible properties: compatible: items: - const: qemu,platform - const: simple-bus ranges: true dma-ranges: true "#address-cells": enum: [ 1, 2 ] "#size-cells": enum: [ 1, 2 ] nonposted-mmio: $ref: /schemas/types.yaml#/definitions/flag description: If present, specifies that direct children of this bus should use non-posted memory accesses (i.e. a non-posted mapping mode) for MMIO ranges. patternProperties: # All other properties should be child nodes with unit-address and 'reg' "@(0|[1-9a-f][0-9a-f]*)$": type: object additionalProperties: false required: - compatible - "#address-cells" - "#size-cells" - ranges ... dt-schema-2022.08.2/dtschema/schemas/cache-controller.yaml000066400000000000000000000020441427720614200232240ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2019 Linaro Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/cache-controller.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: Common Cache Binding maintainers: - Rob Herring properties: $nodename: pattern: "^(cache-controller|cpu)(@[0-9a-f,]+)*$" cache-level: $ref: "/schemas/types.yaml#/definitions/uint32" maximum: 32 cache-unified: $ref: "/schemas/types.yaml#/definitions/flag" next-level-cache: $ref: "/schemas/types.yaml#/definitions/phandle" patternProperties: "^(i-|d-|)cache-size$": $ref: "/schemas/types.yaml#/definitions/uint32" "^(i-|d-|)cache-sets$": $ref: "/schemas/types.yaml#/definitions/uint32" "^(i-|d-|)cache-block-size$": $ref: "/schemas/types.yaml#/definitions/uint32" "^(i-|d-|)cache-line-size$": $ref: "/schemas/types.yaml#/definitions/uint32" if: properties: $nodename: pattern: "^cache-controller.*" then: required: - cache-level additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/chosen.yaml000066400000000000000000000167601427720614200212710ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-clause # Copyright 2014,2018 Linaro Ltd. # # Descriptions based on chosen.txt from Linux kernel # Copyright 2017 Kees Cook # Copyright 2017 Jonathan Neuschäfer # Copyright ARM Ltd 2017 # Copyright 2015 Freescale Semiconductor, Inc. %YAML 1.2 --- $id: http://devicetree.org/schemas/chosen.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: /chosen Node maintainers: - Devicetree Specification Mailing List description: The chosen node does not represent a real device, but serves as a place for passing data between firmware and the operating system, like boot arguments. Data in the chosen node does not represent the hardware. properties: $nodename: const: chosen "#address-cells": true "#size-cells": true ranges: true bootargs: $ref: types.yaml#/definitions/string kaslr-seed: $ref: types.yaml#/definitions/uint64 description: This property is used when booting with CONFIG_RANDOMIZE_BASE as the entropy used to randomize the kernel image base address location. Since it is used directly, this value is intended only for KASLR, and should not be used for other purposes (as it may leak information about KASLR offsets). It is parsed as a u64 value, e.g. /{ chosen { kaslr-seed = <0xfeedbeef 0xc0def00d>; }; }; Note that if this property is set from UEFI (or a bootloader in EFI mode) when EFI_RNG_PROTOCOL is supported, it will be overwritten by the Linux EFI stub (which will populate the property itself, using EFI_RNG_PROTOCOL). rng-seed: $ref: types.yaml#/definitions/uint8-array description: This property served as an entropy to add device randomness. It is parsed as a byte array, e.g. /{ chosen { rng-seed = /bits/ 8 <0x31 0x95 0x1b 0x3c 0xc9 0xfa ...>; }; }; This random value should be provided by bootloader. linux,booted-from-kexec: type: boolean description: This property is set (currently only on PowerPC, and only needed on book3e) by some versions of kexec-tools to tell the new kernel that it is being booted by kexec, as the booting environment may differ (e.g. a different secondary CPU release mechanism). linux,elfcorehdr: $ref: types.yaml#/definitions/uint64-array maxItems: 2 description: | This property holds the memory range, the address and the size, of the elf core header which mainly describes the panicked kernel\'s memory layout as PT_LOAD segments of elf format. / { chosen { linux,elfcorehdr = <0x9 0xfffff000 0x0 0x800>; }; }; While this property does not represent a real hardware, the address and the size are expressed in #address-cells and #size-cells, respectively, of the root node. linux,usable-memory-range: $ref: types.yaml#/definitions/uint64-array maxItems: 2 description: | This property holds a base address and size, describing a limited region in which memory may be considered available for use by the kernel. Memory outside of this range is not available for use. This property describes a limitation: memory within this range is only valid when also described through another mechanism that the kernel would otherwise use to determine available memory (e.g. memory nodes or the EFI memory map). Valid memory may be sparse within the range. / { chosen { linux,usable-memory-range = <0x9 0xf0000000 0x0 0x10000000>; }; }; The main usage is for crash dump kernel to identify its own usable memory and exclude, at its boot time, any other memory areas that are part of the panicked kernel\'s memory. While this property does not represent a real hardware, the address and the size are expressed in #address-cells and #size-cells, respectively, of the root node. linux,initrd-start: $ref: types.yaml#/definitions/uint32 description: These properties hold the physical start and end address of an initrd that\'s loaded by the bootloader. Note that linux,initrd-start is inclusive, but linux,initrd-end is exclusive. linux,initrd-end: $ref: types.yaml#/definitions/uint32 description: These properties hold the physical start and end address of an initrd that\'s loaded by the bootloader. Note that linux,initrd-start is inclusive, but linux,initrd-end is exclusive. linux,pci-probe-only: $ref: types.yaml#/definitions/uint32 enum: [ 0, 1 ] description: Optional property which takes a single-cell argument. If '0', then Linux will assign devices in its usual manner, otherwise it will not try to assign devices and instead use them as they are configured already. stdout-path: $ref: types.yaml#/definitions/string pattern: "^[a-zA-Z0-9@/,+\\-._]*(:[0-9]*[noe]?[78]?[r]?)?$" description: | Device trees may specify the device to be used for boot console output with a stdout-path property under /chosen, as described in the Devicetree Specification, e.g. / { chosen { stdout-path = "/serial@f00:115200"; }; serial@f00 { compatible = "vendor,some-uart"; reg = <0xf00 0x10>; }; }; If the character ":" is present in the value, this terminates the path. The meaning of any characters following the ":" is device-specific, and must be specified in the relevant binding documentation. For UART devices, the preferred binding is a string in the form: {{{}}} where baud - baud rate in decimal parity - 'n' (none), 'o', (odd) or 'e' (even) bits - number of data bits flow - 'r' (rts) For example: 115200n8r Implementation note: Linux will look for the property "linux,stdout-path" or on PowerPC "stdout" if "stdout-path" is not found. However, the "linux,stdout-path" and "stdout" properties are deprecated. New platforms should only use the "stdout-path" property. linux,ima-kexec-buffer: $ref: types.yaml#definitions/uint64-array maxItems: 2 description: This property(currently used by powerpc, arm64) holds the memory range, "the address and the size", of the Integrity Measuremnet Architecture(IMA) measurement logs that are being carried over to the new kernel. / { chosen { linux,ima-kexec-buffer = <0x9 0x82000000 0x0 0x00008000>; }; }; This property does not represent real hardware, but the memory allocated for carrying the IMA measurement logs. The address and the suze are expressed in #address-cells and #size-cells, respectively of the root node. u-boot,bootconf: $ref: types.yaml#/definitions/string description: This property can be used by U-Boot to pass the selected configuration unit name of the booted image down to the operating system. u-boot,version: $ref: types.yaml#/definitions/string pattern: "^20[0-9]{2}\\.[0-9]{2}.*$" description: This property is used by U-Boot to pass its version down to the operating system. patternProperties: "^framebuffer": true additionalProperties: false dt-schema-2022.08.2/dtschema/schemas/clock/000077500000000000000000000000001427720614200202075ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/clock/clock.yaml000066400000000000000000000140671427720614200221760ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2012 Secret Lab Technologies Ltd. %YAML 1.2 --- $id: "http://devicetree.org/schemas/clock/clock.yaml#" $schema: "http://devicetree.org/meta-schemas/base.yaml#" title: Clock binding devicetree schema maintainers: - Michael Turquette - Stephen Boyd description: | Sources of clock signal can be represented by any node in the device tree. Those nodes are designated as clock providers. Clock consumer nodes use a phandle and clock specifier pair to connect clock provider outputs to clock inputs. Similar to the gpio specifiers, a clock specifier is an array of zero, one or more cells identifying the clock output on a device. The length of a clock specifier is defined by the value of a #clock-cells property in the clock provider node. Assigned clock parents and rates -------------------------------- Some platforms may require initial configuration of default parent clocks and clock frequencies. Such a configuration can be specified in a device tree node through assigned-clocks, assigned-clock-parents and assigned-clock-rates properties. The assigned-clock-parents property should contain a list of parent clocks in the form of a phandle and clock specifier pair and the assigned-clock-rates property should contain a list of frequencies in Hz. Both these properties should correspond to the clocks listed in the assigned-clocks property. To skip setting parent or rate of a clock its corresponding entry should be set to 0, or can be omitted if it is not followed by any non-zero entry. serial@a000 { compatible = "fsl,imx-uart"; reg = <0xa000 0x1000>; ... clocks = <&osc 0>, <&pll 1>; clock-names = "baud", "register"; assigned-clocks = <&clkcon 0>, <&pll 2>; assigned-clock-parents = <&pll 2>; assigned-clock-rates = <0>, <460800>; }; In this example the <&pll 2> clock is set as parent of clock <&clkcon 0> and the <&pll 2> clock is assigned a frequency value of 460800 Hz. Configuring a clock's parent and rate through the device node that consumes the clock can be done only for clocks that have a single user. Specifying conflicting parent or rate configuration in multiple consumer nodes for a shared clock is forbidden. Configuration of common clocks, which affect multiple consumer devices can be similarly specified in the clock provider node. # always select the core schema select: true properties: # Legacy clock properties clock-frequency: description: Legacy property for single, fixed frequency clocks anyOf: - $ref: "/schemas/types.yaml#/definitions/uint32" - $ref: "/schemas/types.yaml#/definitions/uint64" bus-frequency: description: Legacy property for fixed bus frequencies $ref: "/schemas/types.yaml#/definitions/uint32" # Provider properties "#clock-cells": description: Number of cells in a clock specifier; Typically 0 for nodes with a single clock output and 1 for nodes with multiple clock outputs. clock-output-names: description: | Recommended to be a list of strings of clock output signal names indexed by the first cell in the clock specifier. However, the meaning of clock-output-names is domain specific to the clock provider, and is only provided to encourage using the same meaning for the majority of clock providers. This format may not work for clock providers using a complex clock specifier format. In those cases it is recommended to omit this property and create a binding specific names property. Clock consumer nodes must never directly reference the provider\'s clock-output-names property. clock-indices: $ref: "/schemas/types.yaml#/definitions/uint32-array" description: If the identifying number for the clocks in the node is not linear from zero, then this allows the mapping of identifiers into the clock-output-names array. # Consumer properties clocks: anyOf: - type: object # for nodes named 'clocks' - $ref: "/schemas/types.yaml#/definitions/phandle-array" description: | List of phandle and clock specifier pairs, one pair for each clock input to the device. Note: if the clock provider specifies '0' for #clock-cells, then only the phandle portion of the pair will appear. clock-names: $ref: "/schemas/types.yaml#/definitions/string-array" description: List of clock input name strings sorted in the same order as the clocks property. Consumers drivers will use clock-names to match clock input names with clocks specifiers. clock-ranges: type: boolean description: Empty property indicating that child nodes can inherit named clocks from this node. Useful for bus nodes to provide a clock to their children. assigned-clocks: $ref: "/schemas/types.yaml#/definitions/phandle-array" assigned-clock-parents: $ref: "/schemas/types.yaml#/definitions/phandle-array" assigned-clock-rates: $ref: "/schemas/types.yaml#/definitions/uint32-array" protected-clocks: $ref: "/schemas/types.yaml#/definitions/uint32-array" description: Some platforms or firmwares may not fully expose all the clocks to the OS, such as in situations where those clks are used by drivers running in ARM secure execution levels. Such a configuration can be specified in devicetree with the protected-clocks property in the form of a clock specifier list. This property should only be specified in the node that is providing the clocks being protected. dependentRequired: clock-names: [clocks] clock-output-names: ["#clock-cells"] clock-indices: [clock-output-names] clock-ranges: [clocks] assigned-clock-parents: [assigned-clocks] assigned-clock-rates: [assigned-clocks] protected-clocks: ["#clock-cells"] dependentSchemas: assigned-clocks: anyOf: - required: [clocks] - required: ["#clock-cells"] additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/cpus.yaml000066400000000000000000000114021427720614200207500ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0 OR BSD-2-clause # Copyright (C) 2018-2019 SiFive, Inc. # # Description text is from the Devicetree Specification at # https://www.devicetree.org/specifications/ # which is # Copyright 2008,2011 Power.org, Inc. # Copyright 2008,2011 Freescale Semiconductor, Inc. # Copyright 2008,2011 International Business Machines Corporation # Copyright 2016,2017 Linaro,Ltd. # Copyright 2016,2017 Arm,Ltd. # %YAML 1.2 --- $id: http://devicetree.org/schemas/cpus.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: Common cpus binding maintainers: - Devicetree Specification Mailing List description: |+ In Devicetree data files, the layout of CPUs is described in the "cpus" node. This node in turn contains a number of subnodes representing CPUs, which define properties for every cpu. Bindings for CPU nodes follow the Devicetree Specification, available from: https://www.devicetree.org/specifications/ properties: $nodename: const: cpus description: A /cpus node is required for all Devicetrees. It does not represent a real device in the system, but acts as a container for child "cpu" nodes which represent the systems' CPUs. '#address-cells': minimum: 1 description: The value specifies how many cells each element of the reg property array takes in children of this node. '#size-cells': const: 0 patternProperties: '^cpu@[0-9a-f]+$': type: object properties: device_type: const: cpu reg: description: Defines a unique CPU/thread ID for the CPU/threads represented by the CPU node. compatible: true clock-frequency: description: Specifies the current clock speed of the CPU in Hertz. timebase-frequency: oneOf: - $ref: /schemas/types.yaml#/definitions/uint32 - $ref: /schemas/types.yaml#/definitions/uint64 minimum: 1 description: Specifies the current frequency at which the timebase and the decrementer registers are updated (in Hertz). status: $ref: "types.yaml#/definitions/string" enum: [ okay, disabled, fail ] description: A standard property describing the state of a CPU. A CPU may be running ("okay"), in a quiescent state ("disabled") or be not operational or not exist ("fail"). enable-method: $ref: /schemas/types.yaml#/definitions/string-array description: Describes the method by which a CPU in a disabled state is enabled. This property is required for CPUs with a status property with a value of "disabled". The value consists of one or more strings that define the method to release this CPU. If a client program recognizes any of the methods, it may use it. cpu-release-addr: $ref: /schemas/types.yaml#/definitions/uint64 description: This value specifies the physical address of a spin table entry that releases a secondary CPU from its spin loop. cache-op-block-size: $ref: /schemas/types.yaml#/definitions/uint32 description: Specifies the block size in bytes upon which cache block instructions operate. Required if different than the L1 cache block size. reservation-granule-size: $ref: /schemas/types.yaml#/definitions/uint32 description: Specifies the reservation granule size supported by this processor in bytes. mmu-type: $ref: /schemas/types.yaml#/definitions/string description: Specifies the CPU's MMU type. tlb-split: $ref: /schemas/types.yaml#/definitions/flag description: If present, specifies that the TLB has a split configuration, with separate TLBs for instructions and data. If absent, specifies that the TLB has a unified configuration. Required for a CPU with a TLB in a split configuration. patternProperties: "^(i-|d-|)tlb-(size|sets)$": $ref: /schemas/types.yaml#/definitions/uint32 minimum: 1 anyOf: - required: - device_type - required: - reg - required: - compatible dependencies: cpu-release-addr: properties: enable-method: const: spin-table cache-size: [ cache-unified ] cache-sets: [ cache-unified ] cache-block-size: [ cache-unified ] cache-line-size: [ cache-unified ] d-tlb-size: [ tlb-split ] d-tlb-sets: [ tlb-split ] i-tlb-size: [ tlb-split ] i-tlb-sets: [ tlb-split ] required: - '#address-cells' - '#size-cells' additionalProperties: true ... dt-schema-2022.08.2/dtschema/schemas/dma/000077500000000000000000000000001427720614200176555ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/dma/dma.yaml000066400000000000000000000007301427720614200213020ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2019 Linaro Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/dma/dma.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: Common DMA binding maintainers: - Rob Herring # always select the core schema select: true properties: dmas: $ref: "/schemas/types.yaml#/definitions/phandle-array" dma-names: true dependencies: dma-names: [ dmas ] additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/dt-core.yaml000066400000000000000000000050451427720614200213410ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. %YAML 1.2 --- $id: "http://devicetree.org/schemas/dt-core.yaml#" $schema: "http://devicetree.org/meta-schemas/base.yaml#" title: Core devicetree node schema which applies to all nodes description: "Schema for core devicetree bindings" maintainers: - Grant Likely - Rob Herring # always select the core schema select: true properties: $nodename: $ref: "types.yaml#/definitions/string" compatible: $ref: "types.yaml#/definitions/string-array" items: # Keep in sync with make_compatible_schema() pattern: "^[a-zA-Z0-9][a-zA-Z0-9,+\\-._]+$" label: $ref: "types.yaml#/definitions/string" dma-coherent: $ref: "types.yaml#/definitions/flag" dma-noncoherent: $ref: "types.yaml#/definitions/flag" dma-ranges: oneOf: - $ref: "types.yaml#/definitions/flag" - $ref: "types.yaml#/definitions/uint32-matrix" ranges: oneOf: - $ref: "types.yaml#/definitions/flag" - $ref: "types.yaml#/definitions/uint32-matrix" reg: $ref: "types.yaml#/definitions/uint32-matrix" reg-io-width: $ref: "types.yaml#/definitions/uint32" minimum: 1 maximum: 0xf description: Typically, a single set bit indicating the access size, but some uses treat this as a bit mask of allowed sizes. reg-shift: $ref: "types.yaml#/definitions/uint32" enum: [ 0, 1, 2 ] secure-status: $ref: "types.yaml#/definitions/string" enum: [ okay, disabled, reserved ] status: $ref: "types.yaml#/definitions/string" enum: [ okay, disabled, reserved ] phandle: $ref: "types.yaml#/definitions/uint32" patternProperties: "^#.*-cells$": $ref: "types.yaml#/definitions/uint32" maximum: 8 ".*-names$": $ref: "types.yaml#/definitions/non-unique-string-array" ".*-supply$": if: not: { type: object } then: $ref: "types.yaml#/definitions/phandle" # property and node namespace overlaps. Catch both here "^[a-zA-Z0-9][a-zA-Z0-9,+\\-._]{0,63}$": type: [object, array, boolean, 'null'] # Anything with a '@' is definitely a node "^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@[0-9a-fA-F]+(,[0-9a-fA-F]+)*$": type: object # Anything beginnning and ending with '__' is a generated node "^__.*__$": type: object # Anything with a '#' is single cell number "^#[a-zA-Z0-9,+\\-._]{0,63}$": $ref: "types.yaml#/definitions/uint32" dependencies: "#size-cells": [ "#address-cells" ] additionalProperties: false ... dt-schema-2022.08.2/dtschema/schemas/gpio/000077500000000000000000000000001427720614200200525ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/gpio/gpio-consumer.yaml000066400000000000000000000011651427720614200235300ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. $id: "http://devicetree.org/schemas/gpio/gpio-consumer.yaml#" $schema: "http://devicetree.org/meta-schemas/base.yaml#" title: GPIO consumer devicetree schema description: "Schema for GPIO consumer devicetree bindings" maintainers: - Rob Herring # do not select this schema for GPIO hogs select: properties: gpio-hog: false properties: gpios: $ref: "/schemas/types.yaml#/definitions/phandle-array" patternProperties: "(? # select this schema for GPIO hogs select: properties: gpio-hog: true required: - gpio-hog properties: $nodename: pattern: "^(hog-[0-9]+|.+-hog(-[0-9]+)?)$" gpio-hog: $ref: "/schemas/types.yaml#/definitions/flag" gpios: $ref: "/schemas/types.yaml#/definitions/uint32-matrix" input: $ref: "/schemas/types.yaml#/definitions/flag" line-name: $ref: "/schemas/types.yaml#/definitions/string" output-high: $ref: "/schemas/types.yaml#/definitions/flag" output-low: $ref: "/schemas/types.yaml#/definitions/flag" required: - gpio-hog - gpios oneOf: - required: - input - required: - output-high - required: - output-low additionalProperties: false dt-schema-2022.08.2/dtschema/schemas/gpio/gpio.yaml000066400000000000000000000026041427720614200216760ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. $id: "http://devicetree.org/schemas/gpio/gpio.yaml#" $schema: "http://devicetree.org/meta-schemas/base.yaml#" title: GPIO devicetree schema description: "Schema for GPIO devicetree bindings" maintainers: - Rob Herring # always select the core schema select: true properties: "#gpio-cells": true gpio-controller: $ref: "/schemas/types.yaml#/definitions/flag" gpio-line-names: $ref: "/schemas/types.yaml#/definitions/non-unique-string-array" ngpios: $ref: "/schemas/types.yaml#/definitions/uint32" gpio-reserved-ranges: $ref: "/schemas/types.yaml#/definitions/uint32-matrix" items: minItems: 2 maxItems: 2 gpio-ranges: $ref: "/schemas/types.yaml#/definitions/phandle-array" items: items: - description: pin controller phandle - description: GPIO controller offset - description: pin controller offset - description: number of pins gpio: # 'gpio' can appear as a property or node name oneOf: - type: object - $ref: "/schemas/types.yaml#/definitions/phandle-array" dependencies: gpio-controller: ['#gpio-cells'] '#gpio-cells': [ gpio-controller ] gpio-line-names: ['#gpio-cells'] ngpios: ['#gpio-cells'] gpio-reserved-ranges: ['#gpio-cells'] gpio-ranges: ['#gpio-cells'] additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/graph.yaml000066400000000000000000000140521427720614200211030ustar00rootroot00000000000000# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2 --- $id: http://devicetree.org/schemas/graph.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: Common bindings for device graphs description: | The hierarchical organisation of the device tree is well suited to describe control flow to devices, but there can be more complex connections between devices that work together to form a logical compound device, following an arbitrarily complex graph. There already is a simple directed graph between devices tree nodes using phandle properties pointing to other nodes to describe connections that can not be inferred from device tree parent-child relationships. The device tree graph bindings described herein abstract more complex devices that can have multiple specifiable ports, each of which can be linked to one or more ports of other devices. These common bindings do not contain any information about the direction or type of the connections, they just map their existence. Specific properties may be described by specialized bindings depending on the type of connection. To see how this binding applies to video pipelines, for example, see Documentation/devicetree/bindings/media/video-interfaces.txt. Here the ports describe data interfaces, and the links between them are the connecting data buses. A single port with multiple connections can correspond to multiple devices being connected to the same physical bus. maintainers: - Philipp Zabel select: false $defs: endpoint-base: type: object properties: reg: maxItems: 1 remote-endpoint: description: | phandle to an 'endpoint' subnode of a remote device node. $ref: /schemas/types.yaml#/definitions/phandle port-base: type: object description: If there is more than one endpoint node or 'reg' property present in endpoint nodes then '#address-cells' and '#size-cells' properties are required. properties: "#address-cells": const: 1 "#size-cells": const: 0 reg: maxItems: 1 endpoint: type: object patternProperties: "^endpoint@[0-9a-f]+$": $ref: "#/$defs/endpoint-base" required: - reg properties: endpoint: $ref: "#/$defs/endpoint-base" unevaluatedProperties: false port: $ref: "#/$defs/port-base" unevaluatedProperties: false patternProperties: "^endpoint(@[0-9a-f]+)?$": $ref: "#/properties/endpoint" ports: type: object description: If there is more than one port node or 'reg' property present in port nodes then '#address-cells' and '#size-cells' properties are required. In such cases all port nodes can be grouped under 'ports' independently from any other child device nodes a device might have. properties: "#address-cells": const: 1 "#size-cells": const: 0 port: type: object patternProperties: "^port@[0-9a-f]+$": type: object required: - reg oneOf: - required: - port - required: - "#address-cells" - "#size-cells" additionalProperties: false additionalProperties: true examples: # Organisation of ports and endpoints: # # Ports are described by child 'port' nodes contained in the device node. # Each port node contains an 'endpoint' subnode for each remote device port # connected to this port. If a single port is connected to more than one # remote device, an 'endpoint' child node must be provided for each link. # If more than one port is present in a device node or there is more than # one endpoint at a port, or a port node needs to be associated with a # selected hardware interface, a common scheme using '#address-cells', # '#size-cells' and 'reg' properties is used to number the nodes. - | device { #address-cells = <1>; #size-cells = <0>; port@0 { #address-cells = <1>; #size-cells = <0>; reg = <0>; endpoint@0 { reg = <0>; // ... }; endpoint@1 { reg = <1>; // ... }; }; port@1 { reg = <1>; endpoint { // ... }; }; }; # All 'port' nodes can be grouped under an optional 'ports' node, which # allows to specify #address-cells, #size-cells properties for the 'port' # nodes independently from any other child device nodes a device might # have. - | device { // ... ports { #address-cells = <1>; #size-cells = <0>; port@0 { #address-cells = <1>; #size-cells = <0>; reg = <0>; // ... endpoint@0 { reg = <0>; // ... }; endpoint@1 { reg = <1>; // ... }; }; port@1 { #address-cells = <1>; #size-cells = <0>; reg = <1>; // ... }; }; }; # Links between endpoints: # # Each endpoint should contain a 'remote-endpoint' phandle property that # points to the corresponding endpoint in the port of the remote device. # In turn, the remote endpoint should contain a 'remote-endpoint' property. # If it has one, it must not point to anything other than the local endpoint. # Two endpoints with their 'remote-endpoint' phandles pointing at each other # form a link between the containing ports. - | device-1 { port { device_1_output: endpoint { remote-endpoint = <&device_2_input>; }; }; }; device-2 { port { device_2_input: endpoint { remote-endpoint = <&device_1_output>; }; }; }; ... dt-schema-2022.08.2/dtschema/schemas/hwlock/000077500000000000000000000000001427720614200204035ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/hwlock/hwlock-consumer.yaml000066400000000000000000000011211427720614200244020ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2019 ARM Ltd. # Copyright 2019 Linaro Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/hwlock/hwlock-consumer.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: Common H/W Locks Consumer Binding maintainers: - Rob Herring # always select the core schema select: true properties: hwlocks: $ref: "/schemas/types.yaml#/definitions/phandle-array" hwlock-names: $ref: "/schemas/types.yaml#/definitions/string-array" dependencies: hwlock-names: [ hwlocks ] additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/i2c/000077500000000000000000000000001427720614200175715ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/i2c/i2c-controller.yaml000066400000000000000000000127401427720614200233170ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2015,2020 Wolfram Sang # Copyright 2022 Arm Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/i2c/i2c-controller.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Common i2c-controller class maintainers: - Rob Herring properties: $nodename: pattern: "^i2c(@.*)?" i2c-bus: type: object $ref: "#" "#address-cells": const: 1 "#size-cells": const: 0 clock-frequency: minimum: 1000 maximum: 3000000 i2c-scl-falling-time-ns: description: Number of nanoseconds the SCL signal takes to fall; t(f) in the I2C specification. i2c-scl-internal-delay-ns: description: Number of nanoseconds the IP core additionally needs to setup SCL. i2c-scl-rising-time-ns: description: Number of nanoseconds the SCL signal takes to rise; t(r) in the I2C specification. i2c-sda-falling-time-ns: description: Number of nanoseconds the SDA signal takes to fall; t(f) in the I2C specification. i2c-analog-filter: type: boolean description: Enable analog filter for i2c lines. i2c-digital-filter: type: boolean description: Enable digital filter for i2c lines. i2c-digital-filter-width-ns: description: Width of spikes which can be filtered by digital filter (i2c-digital-filter). This width is specified in nanoseconds. i2c-analog-filter-cutoff-frequency: $ref: /schemas/types.yaml#/definitions/uint32 description: Frequency that the analog filter (i2c-analog-filter) uses to distinguish which signal to filter. Signal with higher frequency than specified will be filtered out. Only lower frequency will pass (this is applicable to a low-pass analog filter). Typical value should be above the normal i2c bus clock frequency (clock-frequency). Specified in Hz. mctp-controller: type: boolean description: Indicates that the system is accessible via this bus as an endpoint for MCTP over I2C transport. multi-master: type: boolean description: States that there is another master active on this bus. The OS can use this information to adapt power management to keep the arbitration awake all the time, for example. Can not be combined with 'single-master'. scl-gpios: maxItems: 1 description: Specifies the GPIO related to SCL pin. Used for GPIO bus recovery. sda-gpios: maxItems: 1 description: Specifies the GPIO related to SDA pin. Optional for GPIO bus recovery. single-master: type: boolean description: States that there is no other master active on this bus. The OS can use this information to detect a stalled bus more reliably, for example. Can not be combined with 'multi-master'. smbus: type: boolean description: States that additional SMBus restrictions and features apply to this bus. An example of feature is SMBusHostNotify. Examples of restrictions are more reserved addresses and timeout definitions. smbus-alert: type: boolean description: states that the optional SMBus-Alert feature apply to this bus. no-detect: type: boolean description: States that no other devices are present on this bus other than the ones listed in the devicetree. patternProperties: '@[0-9a-f]+$': type: object properties: reg: items: items: - oneOf: - maximum: 0x7f - minimum: 0x40000000 maximum: 0x4000007f - minimum: 0x80000000 maximum: 0x800003ff - minimum: 0xc0000000 maximum: 0xc00003ff description: | One or many I2C slave addresses. These are usually a 7 bit addresses. However, flags can be attached to an address. I2C_TEN_BIT_ADDRESS is used to mark a 10 bit address. It is needed to avoid the ambiguity between e.g. a 7 bit address of 0x50 and a 10 bit address of 0x050 which, in theory, can be on the same bus. Another flag is I2C_OWN_SLAVE_ADDRESS to mark addresses on which we listen to be devices ourselves. host-notify: type: boolean description: Device uses SMBus host notify protocol instead of interrupt line. Requires being connected to an adapter that supports this feature. interrupts: description: I2C core will treat "irq" interrupt (or the very first interrupt if not using interrupt names) as primary interrupt for the slave. interrupt-names: anyOf: - {} # Any name is allowed. - items: enum: - irq - wakeup - smbus_alert description: Names which are recognized by I2C core, other names are left to individual bindings. wakeup-source: description: Device can be used as a wakeup source. The device should also have "wakeup" interrupt for the device. If "wakeup" interrupt name is not present in the binding, then primary interrupt will be used as wakeup interrupt. required: - reg dependentRequired: i2c-analog-filter-cutoff-frequency: [ i2c-analog-filter ] i2c-digital-filter-width-ns: [ i2c-digital-filter ] additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/iio/000077500000000000000000000000001427720614200176745ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/iio/iio-consumer.yaml000066400000000000000000000023311427720614200231700ustar00rootroot00000000000000# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) %YAML 1.2 --- $id: http://devicetree.org/schemas/iio/iio-consumer.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: Generic IIO consumer-bindings maintainers: - Jonathan Cameron description: This binding describes generic properties a consumer of the channels provided by an IIO device may use. As well, direct readings of channels on an IIO Device, an IIO device can provide services to consumer devices. Thes are in the form of channel readings and properties. For example, an ADC might provide 3 channels to an analog accelerometer so that an accelerometer driver can use them to read the voltages that correspond to the accelerations on the 3 axis and apply appropriate calibration to provide useful outputs. select: true properties: io-channels: $ref: /schemas/types.yaml#/definitions/phandle-array description: > List of phandle and IIO specifier pairs, one pair for each IIO input to the device. Note: if the IIO provider specifies '0' for #io-channel-cells, then only the phandle portion of the pair will appear. dependencies: io-channel-names: [io-channels] additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/iio/iio.yaml000066400000000000000000000023351427720614200213430ustar00rootroot00000000000000# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) %YAML 1.2 --- $id: http://devicetree.org/schemas/iio/iio.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Generic IIO bindings select: true maintainers: - Jonathan Cameron description: This binding describes generic properties that can be applied to an IIO device binding. As well, direct readings of channels on an IIO Device, an IIO device can provide services in the form of readings and properties for channels to consumer devices. For example, an ADC might provide 3 channels to an analog accelerometer so that an accelerometer driver can use them to read the voltages that correspond to the accelerations on the 3 axis. properties: "#io-channel-cells": enum: [0, 1, 2] description: > Number of cells in an IIO specifier; Typically 0 for nodes with a single IIO output and 1 for nodes with multiple IIO outputs. A few unusual devices have a 2 level mapping. mount-matrix: $ref: /schemas/types.yaml#/definitions/non-unique-string-array minItems: 9 maxItems: 9 description: 3x3 matrix specifying the sensor orientation wrt to a reference plane. additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/interconnects.yaml000066400000000000000000000007311427720614200226570ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2021 Arm Ltd. $id: "http://devicetree.org/schemas/interconnects.yaml#" $schema: "http://devicetree.org/meta-schemas/base.yaml#" title: Interconnects consumer schema maintainers: - Rob Herring # always select the core schema select: true properties: interconnects: $ref: "types.yaml#/definitions/phandle-array" dependencies: interconnect-names: [interconnects] additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/interrupt-controller.yaml000066400000000000000000000027241427720614200242220ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. $id: "http://devicetree.org/schemas/interrupt-controller.yaml#" $schema: "http://devicetree.org/meta-schemas/base.yaml#" title: Interrupt Controller devicetree node schema maintainers: - Grant Likely - Rob Herring properties: $nodename: pattern: "^interrupt-controller(@[0-9a-f,]+)*$" "#interrupt-cells": true "#address-cells": true interrupt-controller: $ref: "types.yaml#/definitions/flag" interrupt-map: $ref: "/schemas/types.yaml#/definitions/uint32-matrix" interrupt-map-mask: $ref: "types.yaml#/definitions/uint32-array" wakeup-parent: $ref: types.yaml#/definitions/phandle description: Some interrupt controllers in a SoC, are always powered on and have a select interrupts routed to them, so that they can wakeup the SoC from suspend. These interrupt controllers do not fall into the category of a parent interrupt controller and can be specified by the "wakeup-parent" property and contain a single phandle referring to the wakeup capable interrupt controller. dependencies: interrupt-controller: ['#interrupt-cells'] interrupt-map: ['#interrupt-cells' ] interrupt-map-mask: [ interrupt-map ] "#interrupt-cells": anyOf: - required: - interrupt-controller - required: - interrupt-map additionalProperties: true ... dt-schema-2022.08.2/dtschema/schemas/interrupts.yaml000066400000000000000000000015131427720614200222170ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. $id: "http://devicetree.org/schemas/interrupts.yaml#" $schema: "http://devicetree.org/meta-schemas/base.yaml#" title: Interrupt consumer devicetree node schema maintainers: - Grant Likely - Rob Herring # always select the core schema select: true properties: interrupt-parent: $ref: "types.yaml#/definitions/phandle" interrupts: $ref: "types.yaml#/definitions/uint32-matrix" interrupt-names: $ref: "/schemas/types.yaml#/definitions/string-array" interrupts-extended: $ref: "types.yaml#/definitions/phandle-array" dependencies: interrupt-names: oneOf: - required: - interrupts - required: - interrupts-extended additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/iommu/000077500000000000000000000000001427720614200202425ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/iommu/iommu.yaml000066400000000000000000000006501427720614200222550ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/iommu/iommu.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: Common IOMMU Binding maintainers: - Rob Herring # always select the core schema select: true properties: iommus: $ref: "/schemas/types.yaml#/definitions/phandle-array" additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/isa/000077500000000000000000000000001427720614200176705ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/isa/isa-bridge.yaml000066400000000000000000000015371427720614200225700ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2022 Arm Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/isa/isa-bridge.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: ISA bus bridge schema description: | Schema for ISA bridge nodes. This is for bridges with I/O space mapped into the parent bus. ISA Bus Binding to: IEEE Std 1275-1994 https://www.devicetree.org/open-firmware/bindings/isa/isa0_4d.ps maintainers: - Rob Herring select: properties: compatible: contains: enum: - isa - pciclass,0601 device_type: const: isa anyOf: - required: [ device_type ] - required: [ compatible ] allOf: - $ref: isa-bus.yaml# properties: compatible: enum: - isa - pciclass,0601 required: - ranges unevaluatedProperties: false dt-schema-2022.08.2/dtschema/schemas/isa/isa-bus.yaml000066400000000000000000000021461427720614200221220ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2022 Arm Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/isa/isa-bus.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: ISA bus schema description: | Common properties for ISA bus nodes ISA Bus Binding to: IEEE Std 1275-1994 https://www.devicetree.org/open-firmware/bindings/isa/isa0_4d.ps maintainers: - Rob Herring properties: $nodename: pattern: "^isa@" device_type: const: isa ranges: description: Required for memory accesses or memory mapped I/O space. Optional if only indirect I/O is supported. "#address-cells": const: 2 "#size-cells": const: 1 patternProperties: '@(m|i?)[0-9a-f]{1,8}$': type: object description: Child devices properties: reg: items: items: - enum: - 0x0 # memory address - 0x1 # I/O address - description: address - description: size required: - reg required: - "#address-cells" - "#size-cells" additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/mbox/000077500000000000000000000000001427720614200200615ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/mbox/mbox-consumer.yaml000066400000000000000000000012471427720614200235470ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2019 ARM Ltd. # Copyright 2019 Linaro Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/mbox/mbox-consumer.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: Common Mailbox Consumer Binding maintainers: - Rob Herring # always select the core schema select: true properties: mboxes: $ref: "/schemas/types.yaml#/definitions/phandle-array" mbox-names: $ref: "/schemas/types.yaml#/definitions/string-array" shmem: $ref: "/schemas/types.yaml#/definitions/phandle-array" items: maxItems: 1 dependencies: mbox-names: [ mboxes ] additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/memory.yaml000066400000000000000000000015731427720614200213160ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/memory.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: /memory nodes description: | Common properties always required in /memory nodes maintainers: - Rob Herring properties: $nodename: const: '/' patternProperties: "^memory(@[0-9a-f]+)?$": type: object additionalProperties: false properties: device_type: const: memory reg: minItems: 1 maxItems: 1024 numa-node-id: $ref: types.yaml#/definitions/uint32 description: For the purpose of identification, each NUMA node is associated with a unique token known as a node id. required: - device_type - reg additionalProperties: true ... dt-schema-2022.08.2/dtschema/schemas/msi-consumer.yaml000066400000000000000000000020711427720614200224210ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2022 Arm Ltd. $id: http://devicetree.org/schemas/msi-consumer.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: MSI consumer properties maintainers: - Rob Herring # always select the core schema select: true properties: msi-parent: description: | A list of phandle + msi-specifier pairs, one for each MSI controller which the device is capable of using. This property is unordered, and MSIs may be allocated from any combination of MSI controllers listed in the msi-parent property. If a device has restrictions on the allocation of MSIs, these restrictions must be described with additional properties. When #msi-cells is non-zero, busses with an msi-parent will require additional properties to describe the relationship between devices on the bus and the set of MSIs they can potentially generate. $ref: types.yaml#/definitions/phandle-array items: minItems: 1 maxItems: 2 additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/options.yaml000066400000000000000000000070701427720614200214770ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-clause # Copyright 2021 Google LLC # %YAML 1.2 --- $id: http://devicetree.org/schemas/options.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: /options Node maintainers: - Simon Glass description: | The '/options' node does not represent a real device, but serves as a place for passing data into and between firmware components, such as memory mappings. Data in the '/options' node does not represent the hardware. It is ignored by operating systems. Properties in this node should be common to (and used by) at least two firmware projects, such as U-Boot and TF-A. Project-specific subnodes can be used for properties which are specific to a single project. This is based on the precedent set by IEEE 1275-1994 IEEE Standard for Boot (Initialization Configuration) Firmware: Core Requirements and Practices at https://www.openfirmware.info/data/docs/of1275.pdf Purpose of '/options' node -------------------------- A common problem with firmware is that many builds are needed to deal with the slight variations between different, related models of the same hardware. For example, one model may have a TPM and another may not. Devicetree provides an excellent solution to this problem, in that the devicetree to actually use on a platform can be injected in the factory based on which model is being manufactured at the time. A related problem causing build proliferation is dealing with the differences between development firmware, developer-friendly firmware (e.g. with all security features present but with the ability to access the command line), test firmware (which runs tests used in the factory), final production firmware (before signing), signed firmware (where the signatures have been inserted) and the like. Ideally all or most of these should use the same firmware build, with just some options to determine the features available. For example, being able to control whether the UART console or JTAG are available, on any image, is a great debugging aid. When the firmware consists of multiple parts (various U-Boot phases, TF-A, OP-TEE), it is helpful that all operate the same way at runtime, regardless of how they were built. This can be achieved by passing the runtime configuration (e.g. 'enable UART console', 'here are your public keys') along the chain through each firmware stage. It is frustrating to have to replicate a bug on production firmware which does not happen on developer firmware, because they are completely different builds. The '/options' node provides useful functionality for this. It allows the different controls to be 'factored out' of the firmware binaries, so they can be controlled separately from the initial source-code build. The node can be easily updated by a build or factory tool and can control various features in the firmware binaries. It is similar in concept to a Kconfig option, except that it can be changed after firmware binaries are built. The '/options' node is similar in concept to /chosen (see chosen.yaml) except that it is for passing information *into* and *between*) firmware components, instead of from firmware to the operating system. Also, while operating systems typically have a (sometimes extremely long) command line, firmware binaries typically do not support this. The devicetree provides a more structured approach in any case. properties: $nodename: const: options "#address-cells": true "#size-cells": true additionalProperties: type: object dt-schema-2022.08.2/dtschema/schemas/options/000077500000000000000000000000001427720614200206075ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/options/u-boot.yaml000066400000000000000000000063531427720614200227070ustar00rootroot00000000000000# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # Copyright 2021 Google LLC %YAML 1.2 --- $id: http://devicetree.org/schemas/options/u-boot.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: U-Boot configuration node maintainers: - Simon Glass description: | The u-boot,config node provides basic configuration information to U-Boot, for use during its execution. It can be used to control U-Boot's behaviour in various ways. properties: $nodename: const: u-boot compatible: const: u-boot,config bootcmd: $ref: /schemas/types.yaml#/definitions/string description: | Allows overwriting of the boot command used by U-Boot on startup. If present, U-Boot uses this command instead. Note that this feature can work even if loading the environment is disabled, e.g. for security reasons. See also bootsecure. bootdelay-sec: description: | Allows selecting of the U-Boot bootdelay, to control whether U-Boot waits on boot or for how long. This allows this option to be configured by the build system or by a previous-stage binary. For example, if the images is being packed for testing or a user holds down a button, it may allow a delay, but disable it for production. If this property is not present, a default value is used instead. Note that this uses the 'sec' property unit, even though it allows a negative value. Values: -1: no bootdelay and the user cannot interrupt boot 0: no bootdelay but use user can still interrupt boot by holding down a key, if enabled >= 1: delay for this many seconds bootsecure: $ref: /schemas/types.yaml#/definitions/uint32 default: 0 maximum: 2 description: | Controls the execution of the boot command in U-Boot, e.g. selecting between using a special function to run commands, or the normal CLI. This can be used in production images, to restrict the amount of parsing done or the options available, to cut back on the available surface for security attacks. Values: 0: normal boot using CLI (default if not present) 1: use secure boot mechanism instead to parse and run commands other values are reserved for future use 2: use simplified command line (e.g. avoid hush) 3... reserved silent-console: $ref: /schemas/types.yaml#/definitions/uint32 default: 0 maximum: 2 description: | This allows the console to be silenced by default on boot. This can allow easy disabling of console output on a production build, for example. When suppressed, the console is still active. This feature only suppresses the console output itself, on all output devices. Values: 0: console output appears as normal (default) 1: console output is suppressed but console recording still operates (if enabled) 2: console output is suppressed and not recorded required: - compatible additionalProperties: false examples: - | options { u-boot { compatible = "u-boot,config"; bootcmd = "vboot go auto"; bootdelay-sec = <(-1)>; bootsecure = <1>; silent-console = <1>; }; }; dt-schema-2022.08.2/dtschema/schemas/pci/000077500000000000000000000000001427720614200176675ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/pci/pci-bus.yaml000066400000000000000000000106701427720614200221210ustar00rootroot00000000000000# SPDX-License-Identifier: (GPL2.0-only OR BSD-2-Clause) # Copyright 2018 Linaro Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/pci/pci-bus.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: PCI bus schema description: | Common properties for PCI host bridge nodes and PCI bus structure. PCI bus bridges have standardized Device Tree bindings: PCI Bus Binding to: IEEE Std 1275-1994 http://www.devicetree.org/open-firmware/bindings/pci/pci2_1.pdf And for the interrupt mapping part: Open Firmware Recommended Practice: Interrupt Mapping http://www.devicetree.org/open-firmware/practice/imap/imap0_9d.pdf maintainers: - Rob Herring properties: $nodename: pattern: "^pcie?@" ranges: oneOf: - $ref: "/schemas/types.yaml#/definitions/flag" - minItems: 1 maxItems: 32 # Should be enough items: minItems: 5 maxItems: 7 additionalItems: true items: - enum: - 0x01000000 - 0x02000000 - 0x03000000 - 0x42000000 - 0x43000000 - 0x81000000 - 0x82000000 - 0x83000000 - 0xc2000000 - 0xc3000000 reg: true dma-ranges: oneOf: - type: boolean - minItems: 1 maxItems: 32 # Should be enough items: minItems: 5 maxItems: 7 additionalItems: true items: - enum: - 0x02000000 - 0x03000000 - 0x42000000 - 0x43000000 "#address-cells": const: 3 "#size-cells": const: 2 device_type: const: pci bus-range: $ref: /schemas/types.yaml#/definitions/uint32-array minItems: 2 maxItems: 2 items: maximum: 255 "#interrupt-cells": const: 1 interrupt-map: true # minItems: 1 # maxItems: 88 # 22 IDSEL x 4 IRQs # items: # minItems: 6 # 3 addr cells, 1 PCI IRQ cell, 1 phandle, 1+ parent addr and IRQ cells # maxItems: 16 interrupt-map-mask: items: - description: PCI high address cell minimum: 0 maximum: 0xf800 - description: PCI mid address cell const: 0 - description: PCI low address cell const: 0 - description: PCI IRQ cell minimum: 0 maximum: 7 linux,pci-domain: $ref: /schemas/types.yaml#/definitions/uint32 max-link-speed: $ref: /schemas/types.yaml#/definitions/uint32 enum: [ 1, 2, 3, 4 ] msi-map: $ref: /schemas/types.yaml#/definitions/uint32-matrix items: minItems: 3 items: - description: The RID base matched by the entry - description: phandle to msi-controller node - description: (optional) The msi-specifier produced for the first RID matched by the entry. Currently, msi-specifier is 0 or 1 cells. - description: The length of consecutive RIDs following the RID base msi-map-mask: description: A mask to be applied to each Requester ID prior to being mapped to an msi-specifier per the msi-map property. $ref: /schemas/types.yaml#/definitions/uint32 num-lanes: description: The number of PCIe lanes $ref: /schemas/types.yaml#/definitions/uint32 enum: [ 1, 2, 4, 8, 16, 32 ] reset-gpios: description: GPIO controlled connection to PERST# signal maxItems: 1 slot-power-limit-milliwatt: description: If present, specifies slot power limit in milliwatts. This property is invalid in host bridge nodes. maxItems: 1 supports-clkreq: type: boolean aspm-no-l0s: description: Disables ASPM L0s capability type: boolean vendor-id: description: The PCI vendor ID $ref: /schemas/types.yaml#/definitions/uint32 device-id: description: The PCI device ID $ref: /schemas/types.yaml#/definitions/uint32 patternProperties: "^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@1?[0-9a-f](,[0-7])?$": type: object properties: compatible: contains: pattern: "^(pci[0-9a-f]{3,4},[0-9a-f]{1,4}|pciclass,[0-9a-f]{4,6})$" reg: items: minItems: 5 maxItems: 5 minItems: 1 maxItems: 6 # Up to 6 BARs required: - reg required: - device_type - ranges - reg - "#address-cells" - "#size-cells" dependentRequired: msi-map-mask: [ msi-map ] additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/pci/pci-iommu.yaml000066400000000000000000000116511427720614200224560ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2016,2022 Arm Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/pci/pci-iommu.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: PCI IOMMU mapping schema description: | This document describes the generic device tree binding for describing the relationship between PCI(e) devices and IOMMU(s). Each PCI(e) device under a root complex is uniquely identified by its Requester ID (AKA RID). A Requester ID is a triplet of a Bus number, Device number, and Function number. For the purpose of this document, when treated as a numeric value, a RID is formatted such that: * Bits [15:8] are the Bus number. * Bits [7:3] are the Device number. * Bits [2:0] are the Function number. * Any other bits required for padding must be zero. IOMMUs may distinguish PCI devices through sideband data derived from the Requester ID. While a given PCI device can only master through one IOMMU, a root complex may split masters across a set of IOMMUs (e.g. with one IOMMU per bus). The generic 'iommus' property is insufficient to describe this relationship, and a mechanism is required to map from a PCI device to its IOMMU and sideband data. maintainers: - Rob Herring select: true properties: iommu-map: description: | Maps a Requester ID to an IOMMU and associated IOMMU specifier data. The property is an arbitrary number of tuples of (rid-base,iommu,iommu-base,length). Any RID r in the interval [rid-base, rid-base + length) is associated with the listed IOMMU, with the IOMMU specifier (r - rid-base + iommu-base). $ref: /schemas/types.yaml#/definitions/uint32-matrix items: items: - description: RID base maximum: 0xffff - description: phandle to IOMMU - description: IOMMU specifier base (currently always 1 cell) - description: Number of RIDs maximum: 0x10000 iommu-map-mask: description: A mask to be applied to each Requester ID prior to being mapped to an IOMMU specifier per the iommu-map property. $ref: /schemas/types.yaml#/definitions/uint32 maximum: 0xffff additionalProperties: true examples: - | / { #address-cells = <1>; #size-cells = <1>; iommu: iommu@a { reg = <0xa 0x1>; compatible = "foo,some-iommu"; #iommu-cells = <1>; }; pci: pci@f { reg = <0xf 0x1>; compatible = "foo,pcie-root-complex"; device_type = "pci"; /* * The sideband data provided to the IOMMU is the RID, * identity-mapped. */ iommu-map = <0x0 &iommu 0x0 0x10000>; }; }; - | / { #address-cells = <1>; #size-cells = <1>; iommu: iommu@a { reg = <0xa 0x1>; compatible = "foo,some-iommu"; #iommu-cells = <1>; }; pci: pci@f { reg = <0xf 0x1>; compatible = "foo,pcie-root-complex"; device_type = "pci"; /* * The sideband data provided to the IOMMU is the RID with the * function bits masked out. */ iommu-map = <0x0 &iommu 0x0 0x10000>; iommu-map-mask = <0xfff8>; }; }; - | / { #address-cells = <1>; #size-cells = <1>; iommu: iommu@a { reg = <0xa 0x1>; compatible = "foo,some-iommu"; #iommu-cells = <1>; }; pci: pci@f { reg = <0xf 0x1>; compatible = "foo,pcie-root-complex"; device_type = "pci"; /* * The sideband data provided to the IOMMU is the RID, * but the high bits of the bus number are flipped. */ iommu-map = <0x0000 &iommu 0x8000 0x8000>, <0x8000 &iommu 0x0000 0x8000>; }; }; - | / { #address-cells = <1>; #size-cells = <1>; iommu_a: iommu@a { reg = <0xa 0x1>; compatible = "foo,some-iommu"; #iommu-cells = <1>; }; iommu_b: iommu@b { reg = <0xb 0x1>; compatible = "foo,some-iommu"; #iommu-cells = <1>; }; iommu_c: iommu@c { reg = <0xc 0x1>; compatible = "foo,some-iommu"; #iommu-cells = <1>; }; pci: pci@f { reg = <0xf 0x1>; compatible = "foo,pcie-root-complex"; device_type = "pci"; /* * Devices with bus number 0-127 are mastered via IOMMU * a, with sideband data being RID[14:0]. * Devices with bus number 128-255 are mastered via * IOMMU b, with sideband data being RID[14:0]. * No devices master via IOMMU c. */ iommu-map = <0x0000 &iommu_a 0x0000 0x8000>, <0x8000 &iommu_b 0x0000 0x8000>; }; }; ... dt-schema-2022.08.2/dtschema/schemas/phy/000077500000000000000000000000001427720614200177145ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/phy/phy-consumer.yaml000066400000000000000000000010711427720614200232300ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2019 ARM Ltd. # Copyright 2019 Linaro Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/phy/phy-consumer.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: Common PHY Consumer Binding maintainers: - Rob Herring # always select the core schema select: true properties: phys: $ref: "/schemas/types.yaml#/definitions/phandle-array" phy-names: $ref: "/schemas/types.yaml#/definitions/string-array" dependencies: phy-names: [ phys ] additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/phy/phy-provider.yaml000066400000000000000000000015561427720614200232370ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2019 Arm Ltd. $id: "http://devicetree.org/schemas/phy/phy-provider.yaml#" $schema: "http://devicetree.org/meta-schemas/base.yaml#" title: Common PHY provider schema maintainers: - Rob Herring properties: $nodename: pattern: "^(|usb-|usb2-|usb3-|pci-|pcie-|sata-)phy(@[0-9a-f,]+)*$" "#phy-cells": true phy-supply: true phy-type: description: Some PHYs can operate in multiple modes. This sets the operating mode of the PHY. This only works for PHY providers with a single PHY as this only allows 1 mode. For instances with multiple PHYs, the mode can be set in the PHY cells. $ref: /schemas/types.yaml#/definitions/uint32 minimum: 1 maximum: 11 required: - "#phy-cells" dependentRequired: phy-type: [ '#phy-cells' ] additionalProperties: true ... dt-schema-2022.08.2/dtschema/schemas/pinctrl/000077500000000000000000000000001427720614200205675ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/pinctrl/pinctrl-consumer.yaml000066400000000000000000000010731427720614200247600ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2019 Linaro Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/pinctrl/pinctrl-consumer.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Common Pin Controller consumer binding maintainers: - Rob Herring # always select the core schema select: true properties: pinctrl-0: true pinctrl-names: true patternProperties: "pinctrl-[0-9]": $ref: "/schemas/types.yaml#/definitions/phandle-array" dependencies: pinctrl-names: [ pinctrl-0 ] additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/power-domain/000077500000000000000000000000001427720614200215155ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/power-domain/power-domain-consumer.yaml000066400000000000000000000011701427720614200266320ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2019 ARM Ltd. # Copyright 2019 Linaro Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/power-domain/power-domain-consumer.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: Common Power Domain Consumer Binding maintainers: - Rob Herring # always select the core schema select: true properties: power-domains: $ref: "/schemas/types.yaml#/definitions/phandle-array" power-domain-names: $ref: "/schemas/types.yaml#/definitions/string-array" dependencies: power-domain-names: [ power-domains ] additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/property-units.yaml000066400000000000000000000066411427720614200230330ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/property-units.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: Standard Unit Suffixes for Property names maintainers: - Devicetree Specification Mailing List description: Properties which have a unit of measure are recommended to have a unit suffix appended to the property name. The list below contains the recommended suffixes. Other variations exist in bindings, but should not be used in new bindings or added here. The inconsistency in the unit prefixes is due to selecting the most commonly used variants. It is also recommended to use the units listed here and not add additional unit prefixes. select: true patternProperties: "-bits$": $ref: "types.yaml#/definitions/uint32-array" description: number of bits "-kBps$": $ref: "types.yaml#/definitions/uint32-array" description: kilobytes per second "-percent$": $ref: "types.yaml#/definitions/uint32-array" description: percentage "-bp$": $ref: "types.yaml#/definitions/uint32-array" description: basis points (1/100 of a percent) # Time/Frequency "-mhz$": $ref: "types.yaml#/definitions/uint32-array" description: megahertz "-hz$": $ref: "types.yaml#/definitions/uint32-matrix" description: hertz (preferred) "-sec$": $ref: "types.yaml#/definitions/uint32-array" description: second "-ms$": $ref: "types.yaml#/definitions/uint32-array" description: millisecond "-us$": $ref: "types.yaml#/definitions/uint32-array" description: microsecond "-ns$": $ref: "types.yaml#/definitions/uint32-array" description: nanosecond "-ps$": $ref: "types.yaml#/definitions/uint32-array" description: picosecond # Distance "-mm$": $ref: "types.yaml#/definitions/uint32-array" description: millimeter # Electricity "-microamp$": $ref: "types.yaml#/definitions/uint32-array" description: microampere "-nanoamp$": $ref: "types.yaml#/definitions/uint32-array" description: nanoampere "-microamp-hours$": $ref: "types.yaml#/definitions/uint32-array" description: microampere hour "-ohms$": $ref: "types.yaml#/definitions/uint32-array" description: ohm "-micro-ohms$": $ref: "types.yaml#/definitions/uint32-array" description: microohm "-microwatt$": $ref: "types.yaml#/definitions/uint32-array" description: microwatt "-milliwatt$": $ref: "types.yaml#/definitions/uint32-array" description: milliwatt "-microwatt-hours$": $ref: "types.yaml#/definitions/uint32-array" description: microwatt hour "-microvolt$": $ref: "types.yaml#/definitions/uint32-matrix" description: microvolt "-picofarads$": $ref: "types.yaml#/definitions/uint32-array" description: picofarad "-femtofarads$": $ref: "types.yaml#/definitions/uint32-array" description: femtofarad # Temperature "-celsius$": $ref: "types.yaml#/definitions/uint32-array" description: degree Celsius "-millicelsius$": $ref: "types.yaml#/definitions/uint32-array" description: millidegree Celsius "-kelvin$": $ref: "types.yaml#/definitions/uint32-array" description: SI unit of thermodynamic temperature # Pressure "-kpascal$": $ref: "types.yaml#/definitions/uint32-array" description: kilopascal additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/pwm/000077500000000000000000000000001427720614200177175ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/pwm/pwm-consumer.yaml000066400000000000000000000010711427720614200232360ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2019 ARM Ltd. # Copyright 2019 Linaro Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/pwm/pwm-consumer.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: Common PWM Consumer Binding maintainers: - Rob Herring # always select the core schema select: true properties: pwms: $ref: "/schemas/types.yaml#/definitions/phandle-array" pwm-names: $ref: "/schemas/types.yaml#/definitions/string-array" dependencies: pwm-names: [ pwms ] additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/reg.yaml000066400000000000000000000026061427720614200205610ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2020 Arm Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/reg.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: reg property checks description: | Common checks for 'reg' properties maintainers: - Rob Herring select: true properties: {} additionalProperties: true allOf: - if: properties: '#address-cells': const: 2 '#size-cells': const: 2 required: - '#address-cells' - '#size-cells' then: patternProperties: '@': properties: reg: items: minItems: 4 maxItems: 4 - if: properties: '#address-cells': const: 1 '#size-cells': const: 1 required: - '#address-cells' - '#size-cells' then: patternProperties: '@': properties: reg: items: minItems: 2 maxItems: 2 - if: properties: '#address-cells': const: 2 '#size-cells': const: 1 required: - '#address-cells' - '#size-cells' then: patternProperties: '@': properties: reg: items: minItems: 3 maxItems: 3 ... dt-schema-2022.08.2/dtschema/schemas/reset/000077500000000000000000000000001427720614200202365ustar00rootroot00000000000000dt-schema-2022.08.2/dtschema/schemas/reset/reset.yaml000066400000000000000000000010331427720614200222410ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2019 Linaro Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/reset/reset.yaml# $schema: http://devicetree.org/meta-schemas/base.yaml# title: Common Reset Binding maintainers: - Rob Herring # always select the core schema select: true properties: resets: $ref: "/schemas/types.yaml#/definitions/phandle-array" reset-names: $ref: "/schemas/types.yaml#/definitions/string-array" dependencies: reset-names: [ resets ] additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/root-node.yaml000066400000000000000000000032051427720614200217060ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018,2021 Arm Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/root-node.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Common root node description: | Common properties always required in the root node of the tree maintainers: - Device Tree properties: $nodename: const: "/" model: { "$ref" : "types.yaml#/definitions/string-array"} chassis-type: enum: - desktop - laptop - convertible - server - tablet - handset - watch - embedded "#address-cells": enum: [1, 2] "#size-cells": enum: [1, 2] memory: false patternProperties: "@(0|[1-9a-f][0-9a-f]*)$": type: object properties: reg: items: minItems: 2 maxItems: 4 minItems: 1 maxItems: 1024 ranges: oneOf: - items: minItems: 3 maxItems: 7 minItems: 1 maxItems: 1024 - $ref: "types.yaml#/definitions/flag" anyOf: - required: - reg - required: - ranges # Anything else should not have a unit-address "^[^@]+$": true required: - compatible - model - "#address-cells" - "#size-cells" additionalProperties: false examples: - | / { compatible = "acme,boogieboard"; model = "Acme Ltd. Boogieboard developer system"; chassis-type = "embedded"; #address-cells = <1>; #size-cells = <1>; memory@0 { reg = <0 0x10000000>; }; $path = "/"; } dt-schema-2022.08.2/dtschema/schemas/serial.yaml000066400000000000000000000005441427720614200212620ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2019 Linaro Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/serial.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Common Serial binding maintainers: - Rob Herring properties: $nodename: pattern: "^serial(@[0-9a-f,]+)*$" additionalProperties: true dt-schema-2022.08.2/dtschema/schemas/simple-bus.yaml000066400000000000000000000031001427720614200220520ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2021 Arm Ltd. %YAML 1.2 --- $id: http://devicetree.org/schemas/simple-bus.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: simple-bus nodes description: Common simple-bus binding maintainers: - Rob Herring properties: $nodename: pattern: "^([a-z][a-z0-9\\-]+-bus|bus|localbus|soc|axi|ahb|apb)(@.+)?$" compatible: contains: const: simple-bus ranges: true dma-ranges: true "#address-cells": enum: [ 1, 2 ] "#size-cells": enum: [ 1, 2 ] nonposted-mmio: $ref: /schemas/types.yaml#/definitions/flag description: If present, specifies that direct children of this bus should use non-posted memory accesses (i.e. a non-posted mapping mode) for MMIO ranges. patternProperties: # All other properties should be child nodes with unit-address and 'reg' "@(0|[1-9a-f][0-9a-f]*)$": type: object properties: reg: items: minItems: 2 maxItems: 4 minItems: 1 maxItems: 1024 ranges: oneOf: - items: minItems: 3 maxItems: 7 minItems: 1 maxItems: 1024 - $ref: "types.yaml#/definitions/flag" anyOf: - required: - reg - required: - ranges "^[^@]+$": # Only additional properties should be properties, not nodes. not: type: object additionalProperties: false required: - compatible - "#address-cells" - "#size-cells" - ranges dt-schema-2022.08.2/dtschema/schemas/types.yaml000066400000000000000000000160451427720614200211520ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. $id: "http://devicetree.org/schemas/types.yaml#" $schema: "http://devicetree.org/meta-schemas/base.yaml#" title: Core devicetree property data types description: Schema for core devicetree data types. Binding schema can reference these types. maintainers: - Rob Herring select: true definitions: flag: oneOf: - type: boolean const: true - type: 'null' non-unique-string-array: type: array items: { type: string } minItems: 1 string-array: allOf: - $ref: "#/definitions/non-unique-string-array" - uniqueItems: true string: allOf: - $ref: "#/definitions/string-array" - maxItems: 1 uint8-item: type: integer minimum: 0 maximum: 0xff uint8-matrix: type: array typeSize: 8 items: type: array items: $ref: "#/definitions/uint8-item" uint8-array: type: array typeSize: 8 minItems: 1 maxItems: 1 items: type: array items: $ref: "#/definitions/uint8-item" uint8: type: array typeSize: 8 minItems: 1 maxItems: 1 items: type: array items: $ref: "#/definitions/uint8-item" minItems: 1 maxItems: 1 int8-item: type: integer minimum: -128 # maximum: 127 maximum: 0xff int8-matrix: type: array typeSize: 8 items: type: array items: $ref: "#/definitions/int8-item" int8-array: type: array typeSize: 8 minItems: 1 maxItems: 1 items: type: array items: $ref: "#/definitions/int8-item" int8: type: array typeSize: 8 minItems: 1 maxItems: 1 items: type: array items: $ref: "#/definitions/int8-item" minItems: 1 maxItems: 1 uint16-item: type: integer minimum: 0 maximum: 0xffff uint16-matrix: type: array typeSize: 16 items: type: array items: $ref: "#/definitions/uint16-item" uint16-array: type: array typeSize: 16 minItems: 1 maxItems: 1 items: type: array items: $ref: "#/definitions/uint16-item" uint16: type: array typeSize: 16 minItems: 1 maxItems: 1 items: type: array items: $ref: "#/definitions/uint16-item" minItems: 1 maxItems: 1 int16-item: type: integer minimum: -8192 # maximum: 8191 maximum: 0xffff int16-matrix: type: array typeSize: 16 items: type: array items: $ref: "#/definitions/uint16-item" int16-array: type: array typeSize: 16 minItems: 1 maxItems: 1 items: type: array items: $ref: "#/definitions/uint16-item" int16: type: array typeSize: 16 minItems: 1 maxItems: 1 items: type: array items: $ref: "#/definitions/uint16-item" minItems: 1 maxItems: 1 cell: type: integer minimum: 0 maximum: 0xffffffff uint32-matrix: type: array minItems: 1 items: type: array items: $ref: "#/definitions/cell" uint32-array: # For single cell arrays, we need to support encodings as either: # prop = <0x1234 0x5678>; # or # prop = <0x1234>, <0x5678>; anyOf: - type: array minItems: 1 maxItems: 1 items: type: array items: $ref: "#/definitions/cell" - type: array items: type: array minItems: 1 maxItems: 1 items: $ref: "#/definitions/cell" uint32: type: array minItems: 1 maxItems: 1 items: type: array items: $ref: "#/definitions/cell" minItems: 1 maxItems: 1 int32-item: type: integer minimum: -2147483648 # maximum: 2147483647 maximum: 0xffffffff int32-matrix: type: array minItems: 1 items: type: array items: $ref: "#/definitions/int32-item" int32-array: # For single cell arrays, we need to support encodings as either: # prop = <0x1234 0x5678>; # or # prop = <0x1234>, <0x5678>; anyOf: - type: array minItems: 1 maxItems: 1 items: type: array items: $ref: "#/definitions/int32-item" - type: array items: type: array minItems: 1 maxItems: 1 items: $ref: "#/definitions/int32-item" int32: type: array minItems: 1 maxItems: 1 items: type: array items: $ref: "#/definitions/int32-item" minItems: 1 maxItems: 1 int64-item: type: integer minimum: -9223372036854775808 # maximum: 9223372036854775807 maximum: 0xffffffffffffffff int64: type: array minItems: 1 maxItems: 1 typeSize: 64 items: type: array items: $ref: "#/definitions/int64-item" minItems: 1 maxItems: 1 int64-array: type: array minItems: 1 maxItems: 1 typeSize: 64 items: type: array items: $ref: "#/definitions/int64-item" int64-matrix: type: array minItems: 1 typeSize: 64 items: type: array items: $ref: "#/definitions/int64-item" uint64: oneOf: - type: array minItems: 1 maxItems: 1 items: type: array items: $ref: "#/definitions/cell" minItems: 2 maxItems: 2 - type: array minItems: 1 maxItems: 1 typeSize: 64 items: type: array items: minimum: 0 maximum: 0xffffffffffffffff minItems: 1 maxItems: 1 uint64-array: oneOf: - type: array minItems: 1 maxItems: 1 typeSize: 32 items: type: array items: $ref: "#/definitions/cell" minItems: 2 - type: array minItems: 1 maxItems: 1 typeSize: 64 items: type: array items: minimum: 0 maximum: 0xffffffffffffffff uint64-matrix: oneOf: - type: array minItems: 1 items: type: array items: $ref: "#/definitions/cell" minItems: 2 - type: array minItems: 1 typeSize: 64 items: type: array items: minimum: 0 maximum: 0xffffffffffffffff phandle: type: array minItems: 1 maxItems: 1 items: type: array items: phandle: true type: integer maximum: 0xffffffff minItems: 1 maxItems: 1 phandle-array: type: array minItems: 1 items: type: array minItems: 1 items: - oneOf: - phandle: true type: integer minimum: 1 maximum: 0xffffffff - type: integer const: 0 additionalItems: $ref: "#/definitions/cell" dt-schema-2022.08.2/example-schema.yaml000066400000000000000000000105721427720614200174630ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. %YAML 1.2 --- # All the top-level keys are standard json-schema keywords except for # 'maintainers' and 'select' # $id is a unique idenifier based on the filename $id: "http://devicetree.org/schemas/example-schema.yaml#" $schema: "http://devicetree.org/meta-schemas/core.yaml#" title: An example schema annotated with jsonschema details maintainers: - Rob Herring description: | A more detailed multi-line description of the binding. Details about the hardware device and any links to datasheets can go here. The end of the description is marked by indentation less than the first line in the description. select: false # 'select' is a schema applied to a DT node to determine if this binding # schema should be applied to the node. It is optional and by default the # possible compatible strings are extracted and used to match. properties: # A dictionary of DT properties for this binding schema compatible: # More complicated schema can use oneOf (XOR), anyOf (OR), or allOf (AND) # to handle different conditions. # In this case, it's needed to handle a variable number of values as there # isn't another way to express a constraint of the last string value. # The boolean schema must be a list of schemas. oneOf: - items: # items is a list of possible values for the property. The number of # values is determined by the number of elements in the list. # Order in lists is significant, order in dicts is not # Must be one of the 1st enums followed by the 2nd enum # # Each element in items should be 'enum' or 'const' - enum: - vendor,soc4-ip - vendor,soc3-ip - vendor,soc2-ip - enum: - vendor,soc1-ip # additionalItems being false is implied # minItems/maxItems equal to 2 is implied - items: # 'const' is just a special case of an enum with a single possible value - const: vendor,soc1-ip reg: # The description of each element defines the order and implicitly defines # the number of reg entries items: - description: core registers - description: aux registers # minItems/maxItems equal to 2 is implied reg-names: # The core schema enforces this is a string array items: - const: core - const: aux clocks: # Only a single entry, so just need to set the max number of items. maxItems: 1 clock-names: items: - const: bus interrupts: # Either 1 or 2 interrupts can be present minItems: 1 maxItems: 2 items: - description: tx or combined interrupt - description: rx interrupt description: | A variable number of interrupts warrants a description of what conditions affect the number of interrupts. Otherwise, descriptions on standard properties are not necessary. interrupt-names: # minItems must be specified here because the default would be 2 minItems: 1 items: - const: "tx irq" - const: "rx irq" # Property names starting with '#' must be quoted '#interrupt-cells': # A simple case where the value must always be '2'. # The core schema handles that this must be a single integer. const: 2 interrupt-controller: {} # The core checks this is a boolean, so just have to list it here to be # valid for this binding. clock-frequency: # The type is set in the core schema. Per device schema only need to set # constraints on the possible values. minimum: 100 maximum: 400000 # The value that should be used if the property is not present default: 200 foo-gpios: maxItems: 1 description: A connection of the 'foo' gpio line. vendor,int-property: description: Vendor specific properties must have a description type: integer # A type is also required enum: [2, 4, 6, 8, 10] vendor,bool-property: description: Vendor specific properties must have a description type: boolean required: - compatible - reg - interrupts - interrupt-controller examples: - | /{ compatible = "vendor,soc4-ip", "vendor,soc1-ip"; reg = <0x1000 0x80>, <0x3000 0x80>; reg-names = "core", "aux"; interrupts = <10>; interrupt-controller; }; dt-schema-2022.08.2/setup.py000077500000000000000000000031461427720614200154220ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. import setuptools import glob import os with open("README.md", "r") as fh: long_description = fh.read() data_files = [] os.chdir('dtschema') for filename in glob.iglob("schemas/**/*.yaml", recursive=True): data_files.append(filename) for filename in glob.iglob("meta-schemas/**/*.yaml", recursive=True): data_files.append(filename) os.chdir('..') setuptools.setup( name="dtschema", use_scm_version={ 'write_to': 'dtschema/version.py', 'write_to_template': '__version__ = "{version}"', }, setup_requires = ['setuptools_scm'], author="Rob Herring", author_email="robh@kernel.org", description="DeviceTree validation schema and tools", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/devicetree-org/dt-schema", license="BSD", license_files=["LICENSE.txt"], packages=['dtschema'], package_data={'dtschema': data_files}, scripts=[ 'tools/dt-check-compatible', 'tools/dt-validate', 'tools/dt-doc-validate', 'tools/dt-mk-schema', 'tools/dt-extract-example', 'tools/dt-extract-props', 'tools/dtb2py' ], python_requires='>=3.5', install_requires=[ 'ruamel.yaml>0.15.69', 'jsonschema>=4.1.2,<4.10.0', 'rfc3987', 'pylibfdt', ], classifiers=[ "Programming Language :: Python :: 3", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", ], ) dt-schema-2022.08.2/test/000077500000000000000000000000001427720614200146605ustar00rootroot00000000000000dt-schema-2022.08.2/test/child-node-fail.dts000066400000000000000000000034711427720614200203200ustar00rootroot00000000000000// SPDX-License-Identifier { BSD-2-Clause // Copyright 2018 Linaro Ltd. // Copyright 2018-2022 Arm Ltd. /dts-v1/; /plugin/; // silence any missing phandle references / { model = "none"; compatible = "foo"; #address-cells = <1>; #size-cells = <1>; bad-child-node-missing-req-prop { compatible = "vendor,node-with-child-node"; child-node-fixed-name { vendor,optional-property = <1234>; }; }; bad-child-node-property-value { compatible = "vendor,node-with-child-node"; child-node-fixed-name { vendor,required-property = "a string"; }; }; bad-parent-node-property { compatible = "vendor,node-with-child-node"; foo = <0 1>; child-node-fixed-name { vendor,required-property = <1234>; }; }; bad-child-node-reg-size { compatible = "vendor,node-with-child-node"; child-node-fixed-name { vendor,required-property = <1234>; }; child-node@0 { compatible = "a-child-compatible"; reg = <0 1>, <1 1>; vendor,a-child-property = <2>; }; }; bad-child-node-u32-property { compatible = "vendor,node-with-child-node"; child-node-fixed-name { vendor,required-property = <1234>; }; child-node@0 { compatible = "a-child-compatible"; reg = <0>; vendor,a-child-property = <1>; }; }; bad-child-node-u32-property2 { compatible = "vendor,node-with-child-node"; child-node-fixed-name { vendor,required-property = <1234>; }; child-node@0 { compatible = "a-child-compatible"; reg = <0>; vendor,a-child-property2 = <1>; }; }; bad-child-node-string-property { compatible = "vendor,node-with-child-node"; child-node-fixed-name { vendor,required-property = <1234>; }; child-node@0 { compatible = "a-child-compatible"; reg = <0>; vendor,a-child-property = <2>; vendor,a-child-string-property = "a-string", "bad-string"; }; }; }; dt-schema-2022.08.2/test/child-node.dts000066400000000000000000000011161427720614200174010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright 2018 Linaro Ltd. // Copyright 2018-2022 Arm Ltd. /dts-v1/; /plugin/; // silence any missing phandle references / { model = "none"; compatible = "foo"; #address-cells = <1>; #size-cells = <1>; good-child-node-test { compatible = "vendor,node-with-child-node"; child-node-fixed-name { vendor,required-property = <1234>; }; child-node@0 { compatible = "a-child-compatible"; reg = <0>; vendor,a-child-property = <2>; vendor,a-child-property2 = <4>; vendor,a-child-string-property = "a-string"; }; }; }; dt-schema-2022.08.2/test/conditionals-allof-fail.dts000066400000000000000000000015251427720614200220710ustar00rootroot00000000000000// SPDX-License-Identifier { BSD-2-Clause // Copyright 2019 Maxime Ripard // Copyright 2022 Arm Ltd. /dts-v1/; /plugin/; // silence any missing phandle references / { model = "none"; compatible = "none"; #address-cells = <1>; #size-cells = <1>; bad-child-node-wrong-vendor-property { compatible = "vendor,conditionals-allof-test-controller"; vendor,property = "test"; }; bad-child-node-too-long { compatible = "vendor,conditionals-allof-test-controller"; vendor,property = "test1234", "test12345678"; }; bad-child-node-second-wrong-vendor-property { compatible = "vendor,second-conditionals-allof-test-controller"; vendor,property = "test"; vendor,other-property; }; bad-child-node-second-missing-other-property { compatible = "vendor,second-conditionals-allof-test-controller"; vendor,property = "test5678"; }; };dt-schema-2022.08.2/test/conditionals-allof-pass.dts000066400000000000000000000010161427720614200221170ustar00rootroot00000000000000// SPDX-License-Identifier { BSD-2-Clause // Copyright 2019 Maxime Ripard // Copyright 2022 Arm Ltd. /dts-v1/; /plugin/; // silence any missing phandle references / { model = "none"; compatible = "none"; #address-cells = <1>; #size-cells = <1>; test-controller { compatible = "vendor,conditionals-allof-test-controller"; vendor,property = "test1234"; }; second-test-controller { compatible = "vendor,second-conditionals-allof-test-controller"; vendor,property = "test5678"; vendor,other-property; }; }; dt-schema-2022.08.2/test/conditionals-single-fail.dts000066400000000000000000000011531427720614200222520ustar00rootroot00000000000000// SPDX-License-Identifier { BSD-2-Clause // Copyright 2019 Maxime Ripard // Copyright 2022 Arm Ltd. /dts-v1/; /plugin/; // silence any missing phandle references / { model = "none"; compatible = "none"; #address-cells = <1>; #size-cells = <1>; bad-child-node-wrong-vendor-property { compatible = "vendor,test-controller"; vendor,property = "test"; }; bad-child-node-too-long { compatible = "vendor,test-controller"; vendor,property = "test1234", "test12345678"; }; bad-child-node-second-wrong-vendor-property { compatible = "vendor,second-test-controller"; vendor,property = "test"; }; }; dt-schema-2022.08.2/test/conditionals-single-pass.dts000066400000000000000000000007171427720614200223120ustar00rootroot00000000000000// SPDX-License-Identifier { BSD-2-Clause // Copyright 2019 Maxime Ripard // Copyright 2022 Arm Ltd. /dts-v1/; /plugin/; // silence any missing phandle references / { model = "none"; compatible = "none"; #address-cells = <1>; #size-cells = <1>; test-controller { compatible = "vendor,test-controller"; vendor,property = "test1234"; }; second-test-controller { compatible = "vendor,second-test-controller"; vendor,property = "test5678"; }; }; dt-schema-2022.08.2/test/device-fail.dts000066400000000000000000000075501427720614200175530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright 2018 Linaro Ltd. // Copyright 2018-2022 Arm Ltd. /dts-v1/; /plugin/; // silence any missing phandle references / { model = "none"; compatible = "none"; #address-cells = <1>; #size-cells = <1>; interrupt-controller; #interrupt-cells = <1>; interrupt-controller@0 { // bad-num-interrupts-test: compatible = "vendor,soc1-ip"; reg = <0 0>; interrupt-controller; #interrupt-cells = <2>; interrupts = <10>, <11>, <12>; }; interrupt-controller@1 { // bad-interrupt-type-test: compatible = "vendor,soc1-ip"; reg = <1 0>; interrupt-controller; #interrupt-cells = <2>; interrupts = "string"; }; interrupt-controller@2 { // bad-no-interrupt-cells-test: compatible = "vendor,soc1-ip"; reg = <2 0>; interrupt-controller; interrupts = <10>; }; interrupt-controller@3 { // bad-compatible-test: compatible = "vendor,soc4-ip", "vendor,soc3-ip"; reg = <3 0>; interrupt-controller; #interrupt-cells = <2>; interrupts = <10>; }; interrupt-controller@4 { // bad-compatible-order-test: compatible = "vendor,soc1-ip", "vendor,soc3-ip"; reg = <4 0>; interrupt-controller; #interrupt-cells = <2>; interrupts = <10>; }; interrupt-controller@5 { // bad-compatible-missing-test: compatible = "vendor,soc3-ip"; reg = <5 0>; interrupt-controller; #interrupt-cells = <2>; interrupts = <10>; }; interrupt-controller@6 { // bad-compatible-value-test: compatible = "vendor,undocumented-compatible string", "vendor,soc1-ip"; reg = <6 0>; interrupt-controller; #interrupt-cells = <2>; interrupts = <10>; }; interrupt-controller@7 { // bad-clock-freqency-test: compatible = "vendor,soc1-ip"; reg = <7 0>; interrupt-controller; #interrupt-cells = <2>; interrupts = <10>; clock-frequency = <1>; }; interrupt-controller@8 { // bad-interrupt-names-test1: compatible = "vendor,soc1-ip"; reg = <8 0>; interrupt-controller; #interrupt-cells = <2>; interrupt-names = "a irq"; interrupts = <10>; }; interrupt-controller@9 { // bad-interrupt-names-test2: compatible = "vendor,soc1-ip"; reg = <9 0>; interrupt-controller; #interrupt-cells = <2>; interrupt-names = "tx irq", "rx irq", "bad irq"; interrupts = <10>; }; bad-vendor-bool-prop-test { compatible = "vendor,soc1-ip"; vendor,bool-prop = "true"; }; bad-vendor-int-test { compatible = "vendor,soc1-ip"; vendor,int-prop = <5>; }; bad-vendor-int-array-test { compatible = "vendor,soc1-ip"; vendor,int-array-prop = <5>, <4>; }; bad-vendor-int-array-2-test { compatible = "vendor,soc1-ip"; vendor,int-array-prop-2 = <5 4>; }; bad-vendor-int-array-3-test { compatible = "vendor,soc1-ip"; vendor,int-array-size-only-prop = <5 6 7 8 9 10>; }; bad-vendor-string-test { compatible = "vendor,soc1-ip"; vendor,string-prop = "foobaz"; }; bad-vendor-string-list-test { compatible = "vendor,soc1-ip"; vendor,string-list-prop = "foobar"; }; bad-vendor-int8-prop-test { compatible = "vendor,soc1-ip"; vendor,int8-prop = /bits/ 16 <1>; }; bad-vendor-int8-array-prop-test { compatible = "vendor,soc1-ip"; vendor,int8-array-prop = /bits/ 8 <1>; }; bad-vendor-int16-prop-test { compatible = "vendor,soc1-ip"; vendor,int16-prop = <1>; }; bad-vendor-int16-array-prop-test { compatible = "vendor,soc1-ip"; vendor,int16-array-prop = /bits/ 16 <1 2 3>; }; bad-vendor-int64-prop-test { compatible = "vendor,soc1-ip"; vendor,int64-prop = /bits/ 64 <0x123>; }; bad-vendor-phandle-prop-test { compatible = "vendor,soc1-ip"; vendor,phandle-prop = <&foo 0>, <1>; vendor,phandle-array-prop = <&foo>; }; bad-vendor-phandle-args-len-test { compatible = "vendor,soc1-ip"; vendor,phandle-with-fixed-cells = <&foo 2>; }; bad-vendor-phandle-args-len-test2 { compatible = "vendor,soc1-ip"; vendor,phandle-with-fixed-cells = <&foo 2 3>, <&foo 1>; }; }; dt-schema-2022.08.2/test/device.dts000066400000000000000000000031231427720614200166320ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright 2018 Linaro Ltd. // Copyright 2018-2022 Arm Ltd. /dts-v1/; /plugin/; // silence any missing phandle references / { model = "none"; compatible = "foo"; #address-cells = <1>; #size-cells = <1>; interrupt-controller; #interrupt-cells = <1>; interrupt-controller@0 { compatible = "vendor,soc4-ip", "vendor,soc1-ip"; reg = <0x0 0x4>, <0x8 0x4>; reg-names = "coreAAA", "aux"; interrupt-controller; #interrupt-cells = <2>; interrupts = <10>, <11>; some-gpios = <&gpio0 0>, <&gpio0 1 0>; clocks = <&clk0>; clock-names = "clk1" , "clk2"; vendor,bool-prop; vendor,int-prop = <3>; vendor,int-array-prop = <5 6 7 8>; vendor,int-array-prop-2 = <5 10>; vendor,int-array-size-only-prop = <2 3>; vendor,string-prop = "foo"; vendor,int8-prop = /bits/ 8 <1>; vendor,int8-array-prop = /bits/ 8 <1 2>; vendor,int16-prop = /bits/ 16 <1>; vendor,int16-array-prop = /bits/ 16 <1 2>; vendor,int64-prop = /bits/ 64 <0x100000000>; vendor,phandle-prop = <&a_phandle>; vendor,phandle-array-prop = <&a_phandle>, <&a_phandle>; vendor,string-list-prop = "foobar", "foobaz"; vendor,phandle-with-fixed-cells = <&a_phandle 2 3>; vendor,int64-array-prop = /bits/ 64 <0x10000000 0x1>; }; interrupt-controller@10 { compatible = "vendor,soc1-ip"; interrupt-controller; reg = <0x10 0x4>, <0x8 0x4>; #interrupt-cells = <2>; interrupts = <10>; interrupt-names = "tx irq"; vendor,int-array-prop = <5>, <6>, <7>, <8>; vendor,int-array-size-only-prop = <2>, <3>, <4>; vendor,int64-array-prop = /bits/ 64 <0x10000000 0x1>; }; };dt-schema-2022.08.2/test/schemas/000077500000000000000000000000001427720614200163035ustar00rootroot00000000000000dt-schema-2022.08.2/test/schemas/bad-example.yaml000066400000000000000000000027221427720614200213510ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. %YAML 1.2 --- $id: "http://devicetree.org/schemas/bad-example.yaml" $schema: "http://json-schema.org/draft-07/schema#" title: 0 maintainers: - Bob - 12 - will.e@acme.co.uk description: - The description should not be a sequence. - A sequence is also called an array. properties: compatible: type: integer description: Compatible strings for the board example. enum: - 123 oneOf: - items: - unknown: {} - enum: - 456 - "example,board1-with-soc1" - "example,board2-with-soc1" - const: 789 - items: - enum: - 987 - "example,board-with-soc2" - const: "example,soc2" additionalItems: false minItems: 0 maxItems: 2 reg: minItems: 2 maxItems: 0 interrupts: description: 0 minItems: 0 interrupt-names: rob: {} minItems: 3 items: - "rob" - const: "string_with_illegal characters #?" - const: 0 interrupt-controller: type: integer '#interrupt-cells': const: 'foo' description: 0 gpio-controller: const: 'foo' some-gpio: minItems: 0 some-gpios: description: 0 another-property: description: 0 vendor,property: enum: [ 0, 1, 2 ] required: - model - psci - cpus - 0 bad-key: Only known keys are allowed. dt-schema-2022.08.2/test/schemas/child-node-example.yaml000066400000000000000000000035421427720614200226320ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. %YAML 1.2 --- $id: "http://devicetree.org/schemas/child-node-example.yaml#" $schema: "http://devicetree.org/meta-schemas/core.yaml#" title: A one line title for a good binding maintainers: - Rob Herring properties: compatible: items: - const: vendor,node-with-child-node foo: const: 2 reg: items: - description: core regs - description: aux regs child-node-fixed-name: type: object properties: vendor,required-property: $ref: "/schemas/types.yaml#/definitions/uint32" description: test vendor,optional-property: $ref: "/schemas/types.yaml#/definitions/uint32" description: test required: - vendor,required-property patternProperties: '^child-node@.*$': type: object description: This is a child node. properties: compatible: items: - const: a-child-compatible vendor,a-child-property: allOf: - $ref: "/schemas/types.yaml#/definitions/uint32" - const: 2 description: test vendor,a-child-property2: allOf: - $ref: "/schemas/types.yaml#/definitions/uint32" - oneOf: - description: | Testing for 'oneOf', otherwise this could just be an enum const: 2 - const: 4 description: test reg: maxItems: 1 child-property: type: boolean vendor,a-child-string-property: description: a child string property allOf: - $ref: "/schemas/types.yaml#/definitions/string" - const: "a-string" required: - vendor,a-child-property - reg required: - compatible - child-node-fixed-name additionalProperties: false dt-schema-2022.08.2/test/schemas/conditionals-allof-example.yaml000066400000000000000000000021401427720614200243760ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2019 Maxime Ripard %YAML 1.2 --- $id: "http://devicetree.org/schemas/conditionals-allof-example.yaml#" $schema: "http://devicetree.org/meta-schemas/core.yaml#" title: Test for multiple conditionals statements maintainers: - Maxime Ripard properties: compatible: enum: - vendor,conditionals-allof-test-controller - vendor,second-conditionals-allof-test-controller vendor,property: description: A vendor prop $ref: /schemas/types.yaml#/definitions/string vendor,other-property: description: Other vendor prop type: boolean additionalProperties: false allOf: - if: properties: compatible: const: vendor,conditionals-allof-test-controller then: properties: vendor,property: const: test1234 else: properties: vendor,property: const: test5678 - if: properties: compatible: const: vendor,second-conditionals-allof-test-controller then: required: - vendor,other-property dt-schema-2022.08.2/test/schemas/conditionals-single-example.yaml000066400000000000000000000013651427720614200245720ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2019 Maxime Ripard %YAML 1.2 --- $id: "http://devicetree.org/schemas/conditionals-single-example.yaml#" $schema: "http://devicetree.org/meta-schemas/core.yaml#" title: Test for a single conditionals statement maintainers: - Maxime Ripard properties: compatible: enum: - vendor,test-controller - vendor,second-test-controller vendor,property: description: A vendor prop $ref: /schemas/types.yaml#/definitions/string if: properties: compatible: const: vendor,test-controller then: properties: vendor,property: const: test1234 else: properties: vendor,property: const: test5678 additionalProperties: false dt-schema-2022.08.2/test/schemas/good-example.yaml000066400000000000000000000124401427720614200215510ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. %YAML 1.2 --- $id: "http://devicetree.org/schemas/good-example.yaml#" $schema: "http://devicetree.org/meta-schemas/core.yaml#" title: A one line title for a good binding description: A more detailed description for a good binding example. maintainers: - Rob Herring properties: compatible: oneOf: - items: - enum: - vendor,soc4-ip - vendor,soc3-ip - vendor,soc2-ip - enum: - vendor,soc1-ip - items: - enum: - vendor,soc1-ip reg: maxItems: 2 reg-names: items: - const: "coreAAA" - const: "aux" interrupts: minItems: 1 items: - description: 1st irq - description: 2nd irq interrupt-names: minItems: 1 items: - const: "tx irq" - const: "rx irq" '#interrupt-cells': const: 2 interrupt-controller: {} clock-frequency: minimum: 100 maximum: 400000 clocks: minItems: 1 items: - description: 1st clock - description: 2nd clock clock-names: items: - const: "clk1" - const: "clk2" '#clock-cells': const: 1 clock-output-names: minItems: 1 maxItems: 2 some-gpios: maxItems: 2 a-single-gpios: description: A GPIO that does something maxItems: 1 vendor,bool-prop: $ref: "/schemas/types.yaml#/definitions/flag" description: A vendor specific boolean property vendor,int-prop: $ref: "/schemas/types.yaml#/definitions/uint32" enum: [ 1, 2, 3 ] description: Vendor specific single cell integer property vendor,int-array-prop: $ref: "/schemas/types.yaml#/definitions/uint32-array" items: minimum: 5 maximum: 10 description: Vendor specific integer array property vendor,int-array-prop-2: $ref: "/schemas/types.yaml#/definitions/uint32-array" items: - const: 5 - const: 10 description: Vendor specific integer array property vendor,int-array-size-only-prop: $ref: "/schemas/types.yaml#/definitions/uint32-array" minItems: 2 maxItems: 5 description: Vendor specific integer array property with only a size range. This can use either form of brackets. vendor,string-prop: $ref: "/schemas/types.yaml#/definitions/string" enum: - foo - bar description: Vendor specific single string property vendor,string-list-prop: $ref: "/schemas/types.yaml#/definitions/string-array" items: - const: foobar - const: foobaz description: Vendor specific string list property vendor,int8-prop: $ref: /schemas/types.yaml#/definitions/uint8 description: Vendor specific 8-bit integer property vendor,int8-array-prop: $ref: /schemas/types.yaml#/definitions/uint8-array minItems: 2 maxItems: 3 description: A vendor specific uint8 array property with 2 or 3 entries vendor,int16-prop: $ref: /schemas/types.yaml#/definitions/uint16 enum: [ 1, 2, 3 ] description: Vendor specific 16-bit integer property vendor,int16-array-prop: $ref: /schemas/types.yaml#/definitions/uint16-array items: - const: 1 - const: 2 description: Vendor specific 16-bit integer array property vendor,int64-prop: $ref: /schemas/types.yaml#/definitions/uint64 minimum: 0x1234 description: Vendor specific 16-bit integer property vendor,int64-array-prop: $ref: /schemas/types.yaml#/definitions/uint64-array description: Vendor specific 64-bit integer array property vendor,phandle-prop: $ref: "/schemas/types.yaml#/definitions/phandle" description: Vendor specific single cell phandle property vendor,phandle-array-prop: $ref: "/schemas/types.yaml#/definitions/phandle-array" minItems: 2 items: maxItems: 1 description: Vendor specific array of phandles property vendor,phandle-with-fixed-cells: $ref: "/schemas/types.yaml#/definitions/phandle-array" items: - items: - description: the phandle to something - description: the 1st cell data - description: the 2nd cell data description: Vendor specific array of phandles property required: - compatible additionalProperties: false examples: - | /dts-v1/; /{ model = "ARM Juno development board (r0)"; compatible = "arm,juno", "arm,vexpress"; interrupt-parent = <&gic>; #address-cells = <2>; #size-cells = <2>; cpus { #address-cells = <2>; #size-cells = <0>; A57_0: cpu@0 { compatible = "arm,cortex-a57","arm,armv8"; reg = <0x0 0x0>; device_type = "cpu"; enable-method = "psci"; }; ..... A53_0: cpu@100 { compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x100>; device_type = "cpu"; enable-method = "psci"; }; ..... }; }; dt-schema-2022.08.2/test/simple-bus-fail.dts000066400000000000000000000007331427720614200203700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright 2019-2022 Arm Ltd. /dts-v1/; /plugin/; // silence any missing phandle references / { model = "none"; compatible = "none"; #address-cells = <1>; #size-cells = <1>; bus@8000 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x8000 0x4000>; child@200 {}; }; }; dt-schema-2022.08.2/test/simple-bus-pass.dts000066400000000000000000000015031427720614200204170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause // Copyright 2019-2022 Arm Ltd. /dts-v1/; /plugin/; // silence any missing phandle references / { model = "none"; compatible = "none"; #address-cells = <1>; #size-cells = <1>; bus@1000 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x1000 0x4000>; child@0 { #address-cells = <1>; #size-cells = <1>; ranges = <0 0 0x100>; grand-child@0 { reg = <0 0x100>; }; }; child@100 { reg = <0x100 0x100>; }; }; }; dt-schema-2022.08.2/test/test-dt-validate.py000077500000000000000000000163701427720614200204170ustar00rootroot00000000000000#!/usr/bin/env python3 # # Testcases for the Devicetree schema files and validation library # # Copyright 2018 Arm Ltd. # # SPDX-License-Identifier: BSD-2-Clause # # Testcases are executed by running 'make test' from the top level directory of this repo. import unittest import os import glob import sys import subprocess import tempfile basedir = os.path.dirname(__file__) import jsonschema import dtschema dtschema_dir = os.path.dirname(dtschema.__file__) class TestDTMetaSchema(unittest.TestCase): def setUp(self): self.schema = dtschema.load(os.path.join(basedir, 'schemas/good-example.yaml')) self.bad_schema = dtschema.load(os.path.join(basedir, 'schemas/bad-example.yaml')) def test_metaschema_valid(self): '''The DTValidator metaschema must be a valid Draft7 schema''' jsonschema.Draft7Validator.check_schema(dtschema.DTValidator.META_SCHEMA) def test_all_metaschema_valid(self): '''The metaschema must all be a valid Draft7 schema''' for filename in glob.iglob(os.path.join(dtschema_dir, 'meta-schemas/**/*.yaml'), recursive=True): with self.subTest(schema=filename): schema = dtschema.load_schema(filename) jsonschema.Draft7Validator.check_schema(schema) def test_required_properties(self): dtschema.DTValidator.check_schema(self.schema) def test_required_property_missing(self): for key in self.schema.keys(): if key in ['$schema', 'properties', 'required', 'description', 'examples', 'additionalProperties']: continue with self.subTest(k=key): schema_tmp = self.schema.copy() del schema_tmp[key] self.assertRaises(jsonschema.SchemaError, dtschema.DTValidator.check_schema, schema_tmp) def test_bad_schema(self): '''bad-example.yaml is all bad. There is no condition where it should pass validation''' self.assertRaises(jsonschema.SchemaError, dtschema.DTValidator.check_schema, self.bad_schema) def test_bad_properties(self): for key in self.bad_schema.keys(): if key in ['$schema', 'properties']: continue with self.subTest(k=key): schema_tmp = self.schema.copy() schema_tmp[key] = self.bad_schema[key] self.assertRaises(jsonschema.SchemaError, dtschema.DTValidator.check_schema, schema_tmp) bad_props = self.bad_schema['properties'] schema_tmp = self.schema.copy() for key in bad_props.keys(): with self.subTest(k="properties/"+key): schema_tmp['properties'] = self.schema['properties'].copy() schema_tmp['properties'][key] = bad_props[key] self.assertRaises(jsonschema.SchemaError, dtschema.DTValidator.check_schema, schema_tmp) class TestDTSchema(unittest.TestCase): def test_binding_schemas_valid(self): '''Test that all schema files under ./dtschema/schemas/ validate against the DT metaschema''' for filename in glob.iglob(os.path.join(dtschema_dir, 'schemas/**/*.yaml'), recursive=True): with self.subTest(schema=filename): schema = dtschema.load_schema(filename) dtschema.DTValidator.check_schema(schema) def test_binding_schemas_id_is_unique(self): '''Test that all schema files under ./dtschema/schemas/ validate against the DT metaschema''' ids = [] for filename in glob.iglob(os.path.join(dtschema_dir, 'schemas/**/*.yaml'), recursive=True): with self.subTest(schema=filename): schema = dtschema.load_schema(filename) self.assertEqual(ids.count(schema['$id']), 0) ids.append(schema['$id']) def test_binding_schemas_valid_draft7(self): '''Test that all schema files under ./dtschema/schemas/ validate against the Draft7 metaschema The DT Metaschema is supposed to force all schemas to be valid against Draft7. This test makes absolutely sure that they are. ''' for filename in glob.iglob(os.path.join(dtschema_dir, 'schemas/**/*.yaml'), recursive=True): with self.subTest(schema=filename): schema = dtschema.load_schema(filename) jsonschema.Draft7Validator.check_schema(schema) class TestDTValidate(unittest.TestCase): def setUp(self): self.schemas = list() self.schemas = dtschema.set_schemas([ os.path.join(os.path.abspath(basedir), "schemas/")]) for schema in self.schemas.values(): schema["$select_validator"] = dtschema.DTValidator(schema['select']) def check_node(self, nodename, node, fail): if nodename == "/" or nodename.startswith('__'): return node['$nodename'] = [ nodename ] node_matched = True if fail: node_matched = False with self.assertRaises(jsonschema.ValidationError, msg=nodename): for schema in self.schemas.values(): if schema['$select_validator'].is_valid(node): node_matched = True dtschema.DTValidator(schema).validate(node) else: node_matched = False for schema in self.schemas.values(): if schema['$select_validator'].is_valid(node): node_matched = True self.assertIsNone(dtschema.DTValidator(schema).validate(node)) self.assertTrue(node_matched, msg=nodename) def check_subtree(self, nodename, subtree, fail): self.check_node(nodename, subtree, fail) for name,value in subtree.items(): if isinstance(value, dict): self.check_subtree(name, value, fail) def test_dt_yaml_validation(self): '''Test that all DT files under ./test/ validate against the DT schema (YAML)''' for filename in glob.iglob('test/*.dts'): with self.subTest(schema=filename): expect_fail = "-fail" in filename tmpfile = tempfile.NamedTemporaryFile() # The test files have lots of expected warnings, so send stderr to /dev/null res = subprocess.run(['dtc', '-Oyaml', filename], stdout=tmpfile, stderr=subprocess.PIPE) self.assertEqual(res.returncode, 0, msg='dtc failed:\n' + res.stderr.decode()) testtree = dtschema.load(tmpfile.name)[0] for name,value in testtree.items(): if isinstance(value, dict): self.check_node(name, value, expect_fail) def test_dtb_validation(self): '''Test that all DT files under ./test/ validate against the DT schema (DTB)''' for filename in glob.iglob('test/*.dts'): with self.subTest(schema=filename): expect_fail = "-fail" in filename res = subprocess.run(['dtc', '-Odtb', filename], capture_output=True) testtree = dtschema.dtb.fdt_unflatten(res.stdout) self.assertEqual(res.returncode, 0, msg='dtc failed:\n' + res.stderr.decode()) for name, value in testtree.items(): if isinstance(value, dict): self.check_node(name, value, expect_fail) if __name__ == '__main__': unittest.main() dt-schema-2022.08.2/tools/000077500000000000000000000000001427720614200150415ustar00rootroot00000000000000dt-schema-2022.08.2/tools/dt-check-compatible000077500000000000000000000025031427720614200205660ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # Copyright 2022 Arm Ltd. import signal def sigint_handler(signum, frame): sys.exit(-2) signal.signal(signal.SIGINT, sigint_handler) import sys import os import argparse import dtschema if __name__ == "__main__": ap = argparse.ArgumentParser(fromfile_prefix_chars='@', epilog='Arguments can also be passed in a file prefixed with a "@" character.') ap.add_argument("compatible_str", nargs='+', help="1 or more compatible strings to check for a match") ap.add_argument('-v', '--invert-match', action="store_true", help="invert sense of matching, printing compatible which don't match") ap.add_argument('-V', '--version', help="Print version number", action="version", version=dtschema.__version__) ap.add_argument('-s', '--schema', required=True, help="path to processed schema file or schema directory") args = ap.parse_args() if args.schema != "" and not os.path.exists(args.schema): exit(-1) dtschema.set_schemas([args.schema]) undoc_compats = dtschema.get_undocumented_compatibles(args.compatible_str) if args.invert_match: print(*undoc_compats, sep="\n") else: print(*set(args.compatible_str).difference(undoc_compats), sep="\n") dt-schema-2022.08.2/tools/dt-doc-validate000077500000000000000000000043631427720614200177360ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. import signal def sigint_handler(signum, frame): sys.exit(-2) signal.signal(signal.SIGINT, sigint_handler) import os import sys import ruamel.yaml import dtschema import argparse import glob line_number = False def check_doc(filename): ret = 0 try: testtree = dtschema.load(filename, line_number=line_number) except ruamel.yaml.YAMLError as exc: print(filename + ":" + str(exc.problem_mark.line + 1) + ":" + str(exc.problem_mark.column + 1) + ":", exc.problem, file=sys.stderr) return 1 try: for error in sorted(dtschema.DTValidator.iter_schema_errors(testtree), key=lambda e: e.linecol): print(dtschema.format_error(filename, error, verbose=args.verbose), file=sys.stderr) ret = 1 except: print(filename + ': error checking schema file', file=sys.stderr) return 1 dtschema.DTValidator.check_schema_refs(filename, testtree) dtschema.DTValidator.check_quotes(filename + ":", testtree) return ret if __name__ == "__main__": ap = argparse.ArgumentParser(fromfile_prefix_chars='@', epilog='Arguments can also be passed in a file prefixed with a "@" character.') ap.add_argument("yamldt", nargs='*', type=str, help="Filename of YAML encoded devicetree input file") ap.add_argument('-v', '--verbose', help="verbose mode", action="store_true") ap.add_argument('-n', '--line-number', help="Print line and column numbers (slower)", action="store_true") ap.add_argument('-u', '--url-path', help="Additional search path for references") ap.add_argument('-V', '--version', help="Print version number", action="version", version=dtschema.__version__) args = ap.parse_args() line_number=args.line_number if args.url_path: dtschema.add_schema_path(args.url_path) ret = 0 for f in args.yamldt: if os.path.isdir(f): for filename in glob.iglob(f + "/**/*.yaml", recursive=True): ret = check_doc(filename) if ret != 0: break else: ret = check_doc(f) exit(ret) dt-schema-2022.08.2/tools/dt-extract-example000077500000000000000000000045201427720614200205000ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2019-2022 Arm Ltd. import os import re import sys import ruamel.yaml import argparse interrupt_template = """ interrupt-controller; #interrupt-cells = < {int_cells} >; """ example_template = """ example-{example_num} {{ #address-cells = <1>; #size-cells = <1>; {interrupt} {example} }}; }}; """ example_header = """ /dts-v1/; /plugin/; // silence any missing phandle references """ example_start = """ /{ compatible = "foo"; model = "foo"; #address-cells = <1>; #size-cells = <1>; """ yaml = ruamel.yaml.YAML(typ='safe') if __name__ == "__main__": ex = '// empty' ap = argparse.ArgumentParser() ap.add_argument("yamlfile", type=str, help="Filename of YAML encoded schema input file") args = ap.parse_args() try: binding = yaml.load(open(args.yamlfile, encoding='utf-8').read()) if not isinstance(binding, dict): exit(0) except ruamel.yaml.YAMLError as exc: print(args.yamlfile + ":" + str(exc.problem_mark.line + 1) + ":" + str(exc.problem_mark.column + 1) + ":", exc.problem, file=sys.stderr) exit(1) example_dts = example_header if 'examples' in binding.keys(): for idx,ex in enumerate(binding['examples']): # Check if example contains a root node "/{" root_node = re.search('^/\s*{', ex) if not root_node: try: int_val = re.search('\sinterrupts\s*=\s*<([0-9a-zA-Z |()_]+)>', ex).group(1) int_val = re.sub(r'\(.+|\)', r'0', int_val) int_cells = len(int_val.strip().split()) except: int_cells = 0 example_dts += example_start ex = ' '.join(ex.splitlines(True)) if int_cells > 0: int_props = interrupt_template.format(int_cells=int_cells) else: int_props = "" example_dts += example_template.format(example=ex, example_num=idx, interrupt=int_props) else: example_dts += ex else: example_dts += example_start example_dts += "\n};" print(example_dts) dt-schema-2022.08.2/tools/dt-extract-props000077500000000000000000000035641427720614200202170ustar00rootroot00000000000000#!/usr/bin/python3 # SPDX-License-Identifier: BSD-2-Clause # Copyright 2022 Arm Ltd. import signal def sigint_handler(signum, frame): sys.exit(-2) signal.signal(signal.SIGINT, sigint_handler) import argparse import os import sys import pprint import dtschema strict = False if __name__ == "__main__": ap = argparse.ArgumentParser() ap.add_argument("schema_files", type=str, nargs='*', help="preparsed schema file or list of additional schema files/directories") ap.add_argument('-d', '--duplicates', help="Only output properties with more than one type", action="store_true") ap.add_argument('-v', '--verbose', help="Additional search path for references", action="store_true") ap.add_argument('-V', '--version', help="Print version number", action="version", version=dtschema.__version__) args = ap.parse_args() dtschema.set_schemas(args.schema_files) props = dtschema.extract_types() if args.duplicates: tmp_props = {} for k,v in props.items(): if len(v) > 1: tmp_props[k] = v props = tmp_props if args.verbose: prop_types = props else: prop_types = {} for k,v in props.items(): prop_types[k] = [] for l in v: if 'type' in l: prop_types[k] += [l['type']] try: pprint.pprint(prop_types, compact=True) # flush output here to force SIGPIPE to be triggered # while inside this try block. sys.stdout.flush() except BrokenPipeError: # Python flushes standard streams on exit; redirect remaining output # to devnull to avoid another BrokenPipeError at shutdown devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno()) sys.exit(1) # Python exits with error code 1 on EPIPE dt-schema-2022.08.2/tools/dt-mk-schema000077500000000000000000000027571427720614200172540ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. import signal def sigint_handler(signum, frame): sys.exit(-2) signal.signal(signal.SIGINT, sigint_handler) import os import sys import ruamel.yaml import dtschema import argparse import glob import jsonschema import json if __name__ == "__main__": ap = argparse.ArgumentParser(fromfile_prefix_chars='@', epilog='Arguments can also be passed in a file prefixed with a "@" character.') ap.add_argument("-o", "--outfile", type=str, help="Filename of the processed schema") ap.add_argument("-j", "--json", help="Encode the processed schema in json", action="store_true") ap.add_argument("schemas", nargs='*', type=str, help="Names of directories, or YAML encoded schema files") ap.add_argument('-u', '--useronly', help="Only process user schemas", action="store_true") ap.add_argument('-V', '--version', help="Print version number", action="version", version=dtschema.__version__) args = ap.parse_args() schemas = dtschema.set_schemas(args.schemas, core_schema=(not args.useronly)) if not schemas: exit(-1) if args.outfile: f = open(args.outfile, 'w', encoding='utf-8') else: f = sys.stdout if (args.json): json.dump(schemas, f, indent=4) else: yaml = ruamel.yaml.YAML(typ='safe') yaml.dump(schemas, f) dt-schema-2022.08.2/tools/dt-prop-populate000077500000000000000000000140761427720614200202130ustar00rootroot00000000000000#!/usr/bin/python3 # SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. import argparse import os import sys import glob import re from ruamel import yaml import dtschema bindings_dir = 'Bindings' binding_file = {} class schema_group(): def process_node(self, tree, nodename, node, filename): if not 'compatible' in node.keys(): return if binding_file.get(node['compatible'][0]): return for compat in node['compatible']: if compat in ['isa', 'simple-bus', 'cfi-flash']: return match_compat = node['compatible'][0] best_file_match = '' for root, dirs, files in os.walk(bindings_dir): for file in files: if os.path.splitext(os.path.basename(file))[0] in node['compatible']: best_file_match = os.path.join(root, file) break if best_file_match: break if not best_file_match: binding_file[match_compat] = [] for file,data in historical.items(): for line in data.splitlines(): if not re.search(match_compat, line): continue binding_file[match_compat].append(file) if binding_file[match_compat]: best_file_match = max(set(binding_file[match_compat]), key=binding_file[match_compat].count) if not best_file_match: # print("not found: ", node['compatible']) return print(match_compat + ': ' + best_file_match) f = open(best_file_match, 'r+', encoding='utf-8') rawfile = f.read() top_comment = rawfile.partition('%YAML')[0] try: yamldata = yml.load(rawfile) except (yaml.scanner.ScannerError, yaml.parser.ParserError) as exc: print(best_file_match + ": ", exc) return except yaml.YAMLError as exc: print(best_file_match + ":", exc) return for key in node.keys(): # skip child nodes if isinstance(node[key], dict): continue if key in [ 'status', 'phandle' ]: continue; if key in yamldata['properties'].keys() and yamldata['properties'][key] != {}: if key == 'compatible': if 'const' in yamldata['properties'][key]['items'][0]: if yamldata['properties'][key]['items'][0]['const'] != match_compat: yamldata['properties'][key]['items'][0] = { 'enum': [ match_compat, yamldata['properties'][key]['items'][0]['const'] ] } #print(yamldata['properties'][key]['items'][0]) else: matched = False for c in yamldata['properties'][key]['items'][0]['enum']: if match_compat in c: matched = True break if matched: continue yamldata['properties'][key]['items'][0]['enum'].append(match_compat) #print(yamldata['properties'][key]['items'][0]) continue yamldata['properties'][key] = {} if isinstance(node[key], list) and isinstance(node[key][0], str): count = len(node[key]) str_items = [] for val in node[key]: str_items.append({ 'const': val }) yamldata['properties'][key] = { 'items': str_items } if re.search('^[a-zA-Z].*,', key): # vendor specific properties must have description yamldata['properties'][key]['description'] = 'FIXME' if isinstance(node[key], bool): yamldata['properties'][key]['type'] = 'boolean' if re.search('^#.*-cells$', key): yamldata['properties'][key]['const'] = node[key][0][0] if key == 'reg' and isinstance(node[key][0], list): count = len(node[key]) yamldata['properties'][key] = { 'items': [ 'description' : 'FIXME' ] } f.seek(0) print(top_comment, file=f, end="") yml.dump(yamldata, f) f.truncate() def process_subtree(self, tree, nodename, subtree, filename): self.process_node(tree, nodename, subtree, filename) for name,value in subtree.items(): if type(value) == yaml.comments.CommentedMap: self.process_subtree(tree, name, value, filename) def process_tree(self, filename, dt): for subtree in dt: self.process_subtree(subtree, "/", subtree, filename) if __name__ == "__main__": sg = schema_group() ap = argparse.ArgumentParser() ap.add_argument("yamldt", type=str, help="Filename of YAML encoded devicetree input file") args = ap.parse_args() yml = yaml.YAML() # Setup formatting settings yml.indent(mapping=2, sequence=4, offset=2) yml.explicit_start=True yml.preserve_quotes=True yml.version=(1,2) # assuming yaml docs have the old binding doc historical = {} for file in glob.iglob(bindings_dir + "/**/*.yaml", recursive=True): if not os.path.isfile(file): continue # if the filename has a comma, then it's probably a compatible # string and we should only match it with the algorithm above. if ',' in os.path.basename(file): continue rawfile = open(file, 'r', encoding='utf-8').read() try: historical[file] = yml.load(rawfile)['historical'] except: continue if os.path.isdir(args.yamldt): for filename in glob.iglob(args.yamldt + "/**/*.dt.yaml", recursive=True): testtree = dtschema.load(open(filename, encoding='utf-8').read()) sg.process_tree(filename, testtree) else: testtree = dtschema.load(open(args.yamldt, encoding='utf-8').read()) sg.process_tree(args.yamldt, testtree) dt-schema-2022.08.2/tools/dt-validate000077500000000000000000000162001427720614200171640ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. import signal def sigint_handler(signum, frame): sys.exit(-2) signal.signal(signal.SIGINT, sigint_handler) import sys import os import ruamel.yaml import jsonschema import argparse import glob import dtschema verbose = False show_unmatched = False match_schema_file = None class schema_group(): def __init__(self, schema_file=""): if schema_file != "" and not os.path.exists(schema_file): exit(-1) self.schemas = dtschema.set_schemas([schema_file]) def check_node(self, tree, node, disabled, nodename, fullname, filename): # Hack to save some time validating examples if 'example-0' in node or 'example-' in nodename: return node['$nodename'] = [ nodename ] node_matched = False matched_schemas = [] for schema in self.schemas.values(): if '$select_validator' in schema and schema['$select_validator'].is_valid(node): # We have a match if a conditional schema is selected if schema['select'] != True: matched_schemas.append(schema['$id']) node_matched = True try: errors = sorted(dtschema.DTValidator(schema).iter_errors(node), key=lambda e: e.linecol) for error in errors: # Disabled nodes might not have all the required # properties filled in, such as a regulator or a # GPIO meant to be filled at the DTS level on # boards using that particular node. Thus, if the # node is marked as disabled, let's just ignore # any error message reporting a missing property. if disabled or (isinstance(error.instance, dict) and \ 'status' in error.instance and \ 'disabled' in error.instance['status']): if 'required property' in error.message: continue elif error.context: for e in error.context: if not 'required property' in e.message: break else: continue if schema['$id'] == 'generated-compatibles': if show_unmatched < 1: continue if isinstance(node, ruamel.yaml.comments.CommentedBase): line = node.lc.line col = node.lc.col else: line = 0 col = 0 print("%s:%i:%i: %s: failed to match any schema with compatible: %s" % (filename, line, col, fullname, node['compatible']), file=sys.stderr) continue print(dtschema.format_error(filename, error, nodename=nodename, verbose=verbose) + '\n\tFrom schema: ' + schema['$filename'], file=sys.stderr) except RecursionError as e: print(ap.prog + ": recursion error: Check for prior errors in a referenced schema", file=sys.stderr) if show_matched and matched_schemas: print("%s: %s: matched on schema(s)\n\t" % (filename, fullname) + '\n\t'.join(matched_schemas), file=sys.stderr) if show_unmatched >= 2 and not node_matched: print("%s: %s: failed to match any schema" % (filename, fullname), file=sys.stderr) def check_subtree(self, tree, subtree, disabled, nodename, fullname, filename): if nodename.startswith('__'): return try: disabled = ('disabled' in subtree['status']) except: pass self.check_node(tree, subtree, disabled, nodename, fullname, filename) if fullname != "/": fullname += "/" for name,value in subtree.items(): if isinstance(value, dict): self.check_subtree(tree, value, disabled, name, fullname + name, filename) def check_trees(self, filename, dt): """Check the given DT against all schemas""" for schema in self.schemas.values(): if match_schema_file and match_schema_file not in schema['$filename']: continue schema["$select_validator"] = dtschema.DTValidator(schema['select']) for subtree in dt: self.check_subtree(dt, subtree, False, "/", "/", filename) if __name__ == "__main__": ap = argparse.ArgumentParser(fromfile_prefix_chars='@', epilog='Arguments can also be passed in a file prefixed with a "@" character.') ap.add_argument("yamldt", nargs='*', help="Filename or directory of YAML encoded devicetree input file(s)") ap.add_argument('-s', '--schema', help="preparsed schema file or path to schema files") ap.add_argument('-p', '--preparse', help="preparsed schema file (deprecated, use '-s')") ap.add_argument('-l', '--limit', help="limit validation to schema files matching substring") ap.add_argument('-m', '--show-unmatched', default=0, help="Print out nodes which don't match any schema.\n" \ "Once for only nodes with 'compatible'\n" \ "Twice for all nodes", action="count") ap.add_argument('-M', '--show-matched', help="Print out matching schema for each node", action="store_true") ap.add_argument('-n', '--line-number', help="Print line and column numbers (slower)", action="store_true") ap.add_argument('-v', '--verbose', help="verbose mode", action="store_true") ap.add_argument('-u', '--url-path', help="Additional search path for references") ap.add_argument('-V', '--version', help="Print version number", action="version", version=dtschema.__version__) args = ap.parse_args() verbose = args.verbose show_unmatched = args.show_unmatched show_matched = args.show_matched match_schema_file = args.limit if args.url_path: dtschema.add_schema_path(args.url_path) if args.preparse: sg = schema_group(args.preparse) elif args.schema: sg = schema_group(args.schema) else: sg = schema_group() for d in args.yamldt: if not os.path.isdir(d): continue for filename in glob.iglob(d + "/**/*.yaml", recursive=True): testtree = dtschema.load(filename, line_number=args.line_number) if verbose: print("Check: " + filename) sg.check_trees(filename, testtree) for filename in args.yamldt: if not os.path.isfile(filename): continue testtree = dtschema.load(filename, line_number=args.line_number) if verbose: print("Check: " + filename) sg.check_trees(filename, testtree) dt-schema-2022.08.2/tools/dtb2py000077500000000000000000000024101427720614200161700ustar00rootroot00000000000000#!/usr/bin/python3 # SPDX-License-Identifier: BSD-2-Clause # Copyright 2022 Arm Ltd. import argparse import os import sys import pprint import dtschema strict = False if __name__ == "__main__": ap = argparse.ArgumentParser() ap.add_argument("dtbfile", type=str, help="Schema directories and/or files") ap.add_argument('-s', '--schema', help="path to additional additional schema files") ap.add_argument('-V', '--version', help="Print version number", action="version", version=dtschema.__version__) args = ap.parse_args() if not os.path.isfile(args.dtbfile): exit(1) if args.schema: schemas = [args.schema] else: schemas = [] dtschema.set_schemas(schemas) dt = dtschema.load(args.dtbfile) try: pprint.pprint(dt, compact=True) # flush output here to force SIGPIPE to be triggered # while inside this try block. sys.stdout.flush() except BrokenPipeError: # Python flushes standard streams on exit; redirect remaining output # to devnull to avoid another BrokenPipeError at shutdown devnull = os.open(os.devnull, os.O_WRONLY) os.dup2(devnull, sys.stdout.fileno()) sys.exit(1) # Python exits with error code 1 on EPIPE dt-schema-2022.08.2/tools/extract-compatibles000077500000000000000000000023111427720614200207360ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. import os import sys import ruamel.yaml import argparse yaml = ruamel.yaml.YAML() def item_generator(json_input, lookup_key): if isinstance(json_input, dict): for k, v in json_input.items(): if k == lookup_key: yield v else: for child_val in item_generator(v, lookup_key): yield child_val elif isinstance(json_input, list): for item in json_input: for item_val in item_generator(item, lookup_key): yield item_val if __name__ == "__main__": ap = argparse.ArgumentParser() ap.add_argument("yamlfile", type=str, help="Filename of YAML encoded schema input file") args = ap.parse_args() schema_path = os.getcwd() testtree = yaml.load(open(args.yamlfile, encoding='utf-8').read()) compatible_list = [ ] for l in item_generator(testtree['properties']['compatible'], 'enum'): for _l in l: if _l not in compatible_list: compatible_list.append(_l) for c in compatible_list: print(c) dt-schema-2022.08.2/tools/yaml-format000077500000000000000000000041271427720614200172230ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. import os import sys import argparse import glob from ruamel import yaml def eprint(filename, *args, **kwargs): print(filename + ": warning:", *args, file=sys.stderr, **kwargs) def yaml_format(file, in_place): yml = yaml.YAML() # Setup formatting settings yml.indent(mapping=2, sequence=4, offset=2) yml.explicit_start=True yml.explicit_end=True yml.preserve_quotes=True yml.version=(1,2) yml.width=70 rawfile = open(file, encoding='utf-8').read() top_comment = rawfile.partition('%YAML')[0] print(top_comment, file=sys.stderr) try: yamldata = yml.load(rawfile) except yaml.YAMLError as exc: print(file + ":", exc) exit(-1) yamldata['description'] = yaml.scalarstring.PreservedScalarString(yamldata['description']) # Check that keys are in a defined order key_order = [ "$id", "$schema", "title", "maintainers", "description", "allOf", "properties", "required", "patternProperties" "examples" ]; last_idx = 0 yaml_keys = list(yamldata.keys()) for k in key_order: try: if yaml_keys.index(k) < last_idx: eprint(file, "Expected " + key_order[i] + " for key {0}, found ".format(i) + k) last_idx = yaml_keys.index(k) except: continue if in_place: f = open(file, 'w', encoding='utf-8') else: f = sys.stdout print(top_comment, file=f, end="") yml.dump(yamldata, f) if __name__ == "__main__": ap = argparse.ArgumentParser() ap.add_argument("-i", "--in-place", help="operate in place on ", action="store_true") ap.add_argument("file", type=str, help="Filename of YAML encoded devicetree input file") args = ap.parse_args() if os.path.isdir(args.file): for filename in glob.iglob(args.file + "/**/*.yaml", recursive=True): yaml_format(filename, args.in_place) else: yaml_format(args.file, args.in_place) dt-schema-2022.08.2/tools/yaml2json000077500000000000000000000013761427720614200167140ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # Copyright 2018 Linaro Ltd. # Copyright 2018 Arm Ltd. import sys import argparse import ruamel.yaml import json yaml = ruamel.yaml.YAML() if __name__ == "__main__": ap = argparse.ArgumentParser() ap.add_argument('-o', '--output', nargs=1, help="output to specified file") ap.add_argument("file", type=str, help="Filename of YAML encoded devicetree input file") args = ap.parse_args() yamldata = yaml.load(open(args.file, encoding='utf-8').read()) if args.output and args.output[0]: f = open(args.output[0], 'w', encoding='utf-8') else: f = open(args.file.replace('.yaml', '.json'), 'w', encoding='utf-8') json.dump(yamldata, f)