Commit 3ef2bc09 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'devicetree-for-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux

Pull DeviceTree updates from Rob Herring:

 - fix sparse warnings in drivers/of/

 - add more overlay unittests

 - update dtc to v1.4.4-8-g756ffc4f52f6. This adds more checks on dts
   files such as unit-address formatting and stricter character sets for
   node and property names

 - add a common DT modalias function

 - move trivial-devices.txt up and out of i2c dir

 - ARM NVIC interrupt controller binding

 - vendor prefixes for Sensirion, Dioo, Nordic, ROHM

 - correct some binding file locations

* tag 'devicetree-for-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (24 commits)
  of: fix sparse warnings in fdt, irq, reserved mem, and resolver code
  of: fix sparse warning in of_pci_range_parser_one
  of: fix sparse warnings in of_find_next_cache_node
  of/unittest: Missing unlocks on error
  of: fix uninitialized variable warning for overlay test
  of: fix unittest build without CONFIG_OF_OVERLAY
  of: Add unit tests for applying overlays
  of: per-file dtc compiler flags
  fpga: region: add missing DT documentation for config complete timeout
  of: Add vendor prefix for ROHM Semiconductor
  of: fix "/cpus" reference leak in of_numa_parse_cpu_nodes()
  of: Add vendor prefix for Nordic Semiconductor
  dt-bindings: arm,nvic: Binding for ARM NVIC interrupt controller on Cortex-M
  dtc: update warning settings for new bus and node/property name checks
  scripts/dtc: Update to upstream version v1.4.4-8-g756ffc4f52f6
  scripts/dtc: automate getting dtc version and log in update script
  of: Add function for generating a DT modalias with a newline
  of: fix of_device_get_modalias returned length when truncating buffers
  Documentation: devicetree: move trivial-devices out of I2C realm
  dt-bindings: add vendor prefix for Dioo
  ..
parents 2eecf3a4 17a70355
Device-Tree bindings for Atmel's HLCDC (High LCD Controller) DRM driver Device-Tree bindings for Atmel's HLCDC (High LCD Controller) DRM driver
The Atmel HLCDC Display Controller is subdevice of the HLCDC MFD device. The Atmel HLCDC Display Controller is subdevice of the HLCDC MFD device.
See ../mfd/atmel-hlcdc.txt for more details. See ../../mfd/atmel-hlcdc.txt for more details.
Required properties: Required properties:
- compatible: value should be "atmel,hlcdc-display-controller" - compatible: value should be "atmel,hlcdc-display-controller"
......
...@@ -193,6 +193,8 @@ Optional properties: ...@@ -193,6 +193,8 @@ Optional properties:
- region-freeze-timeout-us : The maximum time in microseconds to wait for - region-freeze-timeout-us : The maximum time in microseconds to wait for
bridges to successfully become disabled before the region has been bridges to successfully become disabled before the region has been
programmed. programmed.
- config-complete-timeout-us : The maximum time in microseconds time for the
FPGA to go to operating mode after the region has been programmed.
- child nodes : devices in the FPGA after programming. - child nodes : devices in the FPGA after programming.
In the example below, when an overlay is applied targeting fpga-region0, In the example below, when an overlay is applied targeting fpga-region0,
......
* ARM Nested Vector Interrupt Controller (NVIC)
The NVIC provides an interrupt controller that is tightly coupled to
Cortex-M based processor cores. The NVIC implemented on different SoCs
vary in the number of interrupts and priority bits per interrupt.
Main node required properties:
- compatible : should be one of:
"arm,v6m-nvic"
"arm,v7m-nvic"
"arm,v8m-nvic"
- interrupt-controller : Identifies the node as an interrupt controller
- #interrupt-cells : Specifies the number of cells needed to encode an
interrupt source. The type shall be a <u32> and the value shall be 2.
The 1st cell contains the interrupt number for the interrupt type.
The 2nd cell is the priority of the interrupt.
- reg : Specifies base physical address(s) and size of the NVIC registers.
This is at a fixed address (0xe000e100) and size (0xc00).
- arm,num-irq-priority-bits: The number of priority bits implemented by the
given SoC
Example:
intc: interrupt-controller@e000e100 {
compatible = "arm,v7m-nvic";
#interrupt-cells = <2>;
#address-cells = <1>;
interrupt-controller;
reg = <0xe000e100 0xc00>;
arm,num-irq-priority-bits = <4>;
};
...@@ -15,7 +15,7 @@ Required properties: ...@@ -15,7 +15,7 @@ Required properties:
The HLCDC IP exposes two subdevices: The HLCDC IP exposes two subdevices:
- a PWM chip: see ../pwm/atmel-hlcdc-pwm.txt - a PWM chip: see ../pwm/atmel-hlcdc-pwm.txt
- a Display Controller: see ../display/atmel-hlcdc-dc.txt - a Display Controller: see ../display/atmel/hlcdc-dc.txt
Example: Example:
......
MOXA ART Ethernet Controller Faraday Ethernet Controller
Required properties: Required properties:
- compatible : Must be "moxa,moxart-mac" - compatible : Must contain "faraday,ftmac", as well as one of
the SoC specific identifiers:
"andestech,atmac100"
"moxa,moxart-mac"
- reg : Should contain register location and length - reg : Should contain register location and length
- interrupts : Should contain the mac interrupt number - interrupts : Should contain the mac interrupt number
......
...@@ -80,6 +80,7 @@ denx Denx Software Engineering ...@@ -80,6 +80,7 @@ denx Denx Software Engineering
devantech Devantech, Ltd. devantech Devantech, Ltd.
digi Digi International Inc. digi Digi International Inc.
digilent Diglent, Inc. digilent Diglent, Inc.
dioo Dioo Microcircuit Co., Ltd
dlg Dialog Semiconductor dlg Dialog Semiconductor
dlink D-Link Corporation dlink D-Link Corporation
dmo Data Modul AG dmo Data Modul AG
...@@ -215,6 +216,7 @@ newhaven Newhaven Display International ...@@ -215,6 +216,7 @@ newhaven Newhaven Display International
ni National Instruments ni National Instruments
nintendo Nintendo nintendo Nintendo
nokia Nokia nokia Nokia
nordic Nordic Semiconductor
nuvoton Nuvoton Technology Corporation nuvoton Nuvoton Technology Corporation
nvd New Vision Display nvd New Vision Display
nvidia NVIDIA nvidia NVIDIA
...@@ -261,6 +263,7 @@ richtek Richtek Technology Corporation ...@@ -261,6 +263,7 @@ richtek Richtek Technology Corporation
ricoh Ricoh Co. Ltd. ricoh Ricoh Co. Ltd.
rikomagic Rikomagic Tech Corp. Ltd rikomagic Rikomagic Tech Corp. Ltd
rockchip Fuzhou Rockchip Electronics Co., Ltd rockchip Fuzhou Rockchip Electronics Co., Ltd
rohm ROHM Semiconductor Co., Ltd
samsung Samsung Semiconductor samsung Samsung Semiconductor
samtec Samtec/Softing company samtec Samtec/Softing company
sandisk Sandisk Corporation sandisk Sandisk Corporation
......
...@@ -410,10 +410,7 @@ static ssize_t name_show(struct device *dev, ...@@ -410,10 +410,7 @@ static ssize_t name_show(struct device *dev,
static ssize_t modalias_show(struct device *dev, static ssize_t modalias_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2); return of_device_modalias(dev, buf, PAGE_SIZE);
buf[len] = '\n';
buf[len+1] = 0;
return len+1;
} }
static struct device_attribute ibmebus_bus_device_attrs[] = { static struct device_attribute ibmebus_bus_device_attrs[] = {
......
...@@ -847,7 +847,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a, ...@@ -847,7 +847,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
int len; int len;
len = of_device_get_modalias(dev, buf, PAGE_SIZE -1); len = of_device_modalias(dev, buf, PAGE_SIZE);
if (len != -ENODEV) if (len != -ENODEV)
return len; return len;
......
...@@ -41,12 +41,7 @@ compatible_show (struct device *dev, struct device_attribute *attr, char *buf) ...@@ -41,12 +41,7 @@ compatible_show (struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t modalias_show (struct device *dev, struct device_attribute *attr, static ssize_t modalias_show (struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
int len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2); return of_device_modalias(dev, buf, PAGE_SIZE);
buf[len] = '\n';
buf[len+1] = 0;
return len+1;
} }
static ssize_t devspec_show(struct device *dev, static ssize_t devspec_show(struct device *dev,
......
...@@ -263,7 +263,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, ...@@ -263,7 +263,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
if (!parser->range || parser->range + parser->np > parser->end) if (!parser->range || parser->range + parser->np > parser->end)
return NULL; return NULL;
range->pci_space = parser->range[0]; range->pci_space = be32_to_cpup(parser->range);
range->flags = of_bus_pci_get_flags(parser->range); range->flags = of_bus_pci_get_flags(parser->range);
range->pci_addr = of_read_number(parser->range + 1, ns); range->pci_addr = of_read_number(parser->range + 1, ns);
range->cpu_addr = of_translate_address(parser->node, range->cpu_addr = of_translate_address(parser->node,
......
...@@ -2281,15 +2281,14 @@ EXPORT_SYMBOL_GPL(of_console_check); ...@@ -2281,15 +2281,14 @@ EXPORT_SYMBOL_GPL(of_console_check);
*/ */
struct device_node *of_find_next_cache_node(const struct device_node *np) struct device_node *of_find_next_cache_node(const struct device_node *np)
{ {
struct device_node *child; struct device_node *child, *cache_node;
const phandle *handle;
handle = of_get_property(np, "l2-cache", NULL); cache_node = of_parse_phandle(np, "l2-cache", 0);
if (!handle) if (!cache_node)
handle = of_get_property(np, "next-level-cache", NULL); cache_node = of_parse_phandle(np, "next-level-cache", 0);
if (handle) if (cache_node)
return of_find_node_by_phandle(be32_to_cpup(handle)); return cache_node;
/* OF on pmac has nodes instead of properties named "l2-cache" /* OF on pmac has nodes instead of properties named "l2-cache"
* beneath CPU nodes. * beneath CPU nodes.
......
...@@ -176,7 +176,7 @@ const void *of_device_get_match_data(const struct device *dev) ...@@ -176,7 +176,7 @@ const void *of_device_get_match_data(const struct device *dev)
} }
EXPORT_SYMBOL(of_device_get_match_data); EXPORT_SYMBOL(of_device_get_match_data);
ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
{ {
const char *compat; const char *compat;
int cplen, i; int cplen, i;
...@@ -223,9 +223,8 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) ...@@ -223,9 +223,8 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
str[i] = '_'; str[i] = '_';
} }
return tsize; return repend;
} }
EXPORT_SYMBOL_GPL(of_device_get_modalias);
int of_device_request_module(struct device *dev) int of_device_request_module(struct device *dev)
{ {
...@@ -250,6 +249,21 @@ int of_device_request_module(struct device *dev) ...@@ -250,6 +249,21 @@ int of_device_request_module(struct device *dev)
} }
EXPORT_SYMBOL_GPL(of_device_request_module); EXPORT_SYMBOL_GPL(of_device_request_module);
/**
* of_device_modalias - Fill buffer with newline terminated modalias string
*/
ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len)
{
ssize_t sl = of_device_get_modalias(dev, str, len - 2);
if (sl < 0)
return sl;
str[sl++] = '\n';
str[sl] = 0;
return sl;
}
EXPORT_SYMBOL_GPL(of_device_modalias);
/** /**
* of_device_uevent - Display OF related uevent information * of_device_uevent - Display OF related uevent information
*/ */
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include <asm/setup.h> /* for COMMAND_LINE_SIZE */ #include <asm/setup.h> /* for COMMAND_LINE_SIZE */
#include <asm/page.h> #include <asm/page.h>
#include "of_private.h"
/* /*
* of_fdt_limit_memory - limit the number of regions in the /memory node * of_fdt_limit_memory - limit the number of regions in the /memory node
* @limit: maximum entries * @limit: maximum entries
...@@ -46,8 +48,8 @@ void of_fdt_limit_memory(int limit) ...@@ -46,8 +48,8 @@ void of_fdt_limit_memory(int limit)
const void *val; const void *val;
int nr_address_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT; int nr_address_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
int nr_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT; int nr_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
const uint32_t *addr_prop; const __be32 *addr_prop;
const uint32_t *size_prop; const __be32 *size_prop;
int root_offset; int root_offset;
int cell_size; int cell_size;
...@@ -469,11 +471,11 @@ static int unflatten_dt_nodes(const void *blob, ...@@ -469,11 +471,11 @@ static int unflatten_dt_nodes(const void *blob,
* Returns NULL on failure or the memory chunk containing the unflattened * Returns NULL on failure or the memory chunk containing the unflattened
* device tree on success. * device tree on success.
*/ */
static void *__unflatten_device_tree(const void *blob, void *__unflatten_device_tree(const void *blob,
struct device_node *dad, struct device_node *dad,
struct device_node **mynodes, struct device_node **mynodes,
void *(*dt_alloc)(u64 size, u64 align), void *(*dt_alloc)(u64 size, u64 align),
bool detached) bool detached)
{ {
int size; int size;
void *mem; void *mem;
...@@ -1261,6 +1263,8 @@ void __init unflatten_device_tree(void) ...@@ -1261,6 +1263,8 @@ void __init unflatten_device_tree(void)
/* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */ /* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
of_alias_scan(early_init_dt_alloc_memory_arch); of_alias_scan(early_init_dt_alloc_memory_arch);
unittest_unflatten_overlay_base();
} }
/** /**
......
...@@ -102,7 +102,7 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) ...@@ -102,7 +102,7 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
__be32 initial_match_array[MAX_PHANDLE_ARGS]; __be32 initial_match_array[MAX_PHANDLE_ARGS];
const __be32 *match_array = initial_match_array; const __be32 *match_array = initial_match_array;
const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 }; const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = cpu_to_be32(~0) };
u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
int imaplen, match, i, rc = -EINVAL; int imaplen, match, i, rc = -EINVAL;
......
...@@ -57,6 +57,8 @@ static void __init of_numa_parse_cpu_nodes(void) ...@@ -57,6 +57,8 @@ static void __init of_numa_parse_cpu_nodes(void)
else else
node_set(nid, numa_nodes_parsed); node_set(nid, numa_nodes_parsed);
} }
of_node_put(cpus);
} }
static int __init of_numa_parse_memory_nodes(void) static int __init of_numa_parse_memory_nodes(void)
......
...@@ -55,6 +55,18 @@ static inline int of_property_notify(int action, struct device_node *np, ...@@ -55,6 +55,18 @@ static inline int of_property_notify(int action, struct device_node *np,
} }
#endif /* CONFIG_OF_DYNAMIC */ #endif /* CONFIG_OF_DYNAMIC */
#if defined(CONFIG_OF_UNITTEST) && defined(CONFIG_OF_OVERLAY)
extern void __init unittest_unflatten_overlay_base(void);
#else
static inline void unittest_unflatten_overlay_base(void) {};
#endif
extern void *__unflatten_device_tree(const void *blob,
struct device_node *dad,
struct device_node **mynodes,
void *(*dt_alloc)(u64 size, u64 align),
bool detached);
/** /**
* General utilities for working with live trees. * General utilities for working with live trees.
* *
......
...@@ -197,7 +197,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem) ...@@ -197,7 +197,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem)
const struct of_device_id *i; const struct of_device_id *i;
for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) { for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) {
reservedmem_of_init_fn initfn = i->data; int const (*initfn)(struct reserved_mem *rmem) = i->data;
const char *compat = i->compatible; const char *compat = i->compatible;
if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) if (!of_flat_dt_is_compatible(rmem->fdt_node, compat))
......
...@@ -92,7 +92,7 @@ static void adjust_overlay_phandles(struct device_node *overlay, ...@@ -92,7 +92,7 @@ static void adjust_overlay_phandles(struct device_node *overlay,
if (phandle == OF_PHANDLE_ILLEGAL) if (phandle == OF_PHANDLE_ILLEGAL)
continue; continue;
*(uint32_t *)prop->value = cpu_to_be32(overlay->phandle); *(__be32 *)prop->value = cpu_to_be32(overlay->phandle);
} }
for_each_child_of_node(overlay, child) for_each_child_of_node(overlay, child)
......
obj-y += testcases.dtb.o obj-y += testcases.dtb.o
obj-y += overlay.dtb.o
obj-y += overlay_bad_phandle.dtb.o
obj-y += overlay_base.dtb.o
targets += testcases.dtb testcases.dtb.S targets += testcases.dtb testcases.dtb.S
targets += overlay.dtb overlay.dtb.S
targets += overlay_bad_phandle.dtb overlay_bad_phandle.dtb.S
targets += overlay_base.dtb overlay_base.dtb.S
.SECONDARY: \ .PRECIOUS: \
$(obj)/testcases.dtb.S \ $(obj)/%.dtb.S \
$(obj)/testcases.dtb $(obj)/%.dtb
# enable creation of __symbols__ node
DTC_FLAGS_overlay := -@
DTC_FLAGS_overlay_bad_phandle := -@
DTC_FLAGS_overlay_base := -@
/dts-v1/;
/plugin/;
/ {
fragment@0 {
target = <&electric_1>;
__overlay__ {
status = "ok";
hvac_2: hvac-large-1 {
compatible = "ot,hvac-large";
heat-range = < 40 75 >;
cool-range = < 65 80 >;
};
};
};
fragment@1 {
target = <&rides_1>;
__overlay__ {
#address-cells = <1>;
#size-cells = <1>;
status = "ok";
ride@200 {
compatible = "ot,ferris-wheel";
reg = < 0x00000200 0x100 >;
hvac-provider = < &hvac_2 >;
hvac-thermostat = < 27 32 > ;
hvac-zones = < 12 5 >;
hvac-zone-names = "operator", "snack-bar";
spin-controller = < &spin_ctrl_1 3 >;
spin-rph = < 30 >;
gondolas = < 16 >;
gondola-capacity = < 6 >;
};
};
};
fragment@2 {
target = <&lights_2>;
__overlay__ {
status = "ok";
color = "purple", "white", "red", "green";
rate = < 3 256 >;
};
};
};
/dts-v1/;
/plugin/;
/ {
fragment@0 {
target = <&electric_1>;
__overlay__ {
// This label should cause an error when the overlay
// is applied. There is already a phandle value
// in the base tree for motor-1.
spin_ctrl_1_conflict: motor-1 {
accelerate = < 3 >;
decelerate = < 5 >;
};
};
};
};
/dts-v1/;
/plugin/;
/*
* Base device tree that overlays will be applied against.
*
* Do not add any properties in node "/".
* Do not add any nodes other than "/testcase-data-2" in node "/".
* Do not add anything that would result in dtc creating node "/__fixups__".
* dtc will create nodes "/__symbols__" and "/__local_fixups__".
*/
/ {
testcase-data-2 {
#address-cells = <1>;
#size-cells = <1>;
electric_1: substation@100 {
compatible = "ot,big-volts-control";
reg = < 0x00000100 0x100 >;
status = "disabled";
hvac_1: hvac-medium-1 {
compatible = "ot,hvac-medium";
heat-range = < 50 75 >;
cool-range = < 60 80 >;
};
spin_ctrl_1: motor-1 {
compatible = "ot,ferris-wheel-motor";
spin = "clockwise";
};
spin_ctrl_2: motor-8 {
compatible = "ot,roller-coaster-motor";
};
};
rides_1: fairway-1 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "ot,rides";
status = "disabled";
orientation = < 127 >;
ride@100 {
compatible = "ot,roller-coaster";
reg = < 0x00000100 0x100 >;
hvac-provider = < &hvac_1 >;
hvac-thermostat = < 29 > ;
hvac-zones = < 14 >;
hvac-zone-names = "operator";
spin-controller = < &spin_ctrl_2 5 &spin_ctrl_2 7 >;
spin-controller-names = "track_1", "track_2";
queues = < 2 >;
};
};
lights_1: lights@30000 {
compatible = "ot,work-lights";
reg = < 0x00030000 0x1000 >;
status = "disabled";
};
lights_2: lights@40000 {
compatible = "ot,show-lights";
reg = < 0x00040000 0x1000 >;
status = "disabled";
rate = < 13 138 >;
};
retail_1: vending@50000 {
reg = < 0x00050000 0x1000 >;
compatible = "ot,tickets";
status = "disabled";
};
};
};
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/hashtable.h> #include <linux/hashtable.h>
#include <linux/libfdt.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_fdt.h> #include <linux/of_fdt.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
...@@ -1925,6 +1926,324 @@ static void __init of_unittest_overlay(void) ...@@ -1925,6 +1926,324 @@ static void __init of_unittest_overlay(void)
static inline void __init of_unittest_overlay(void) { } static inline void __init of_unittest_overlay(void) { }
#endif #endif
/*
* __dtb_ot_begin[] and __dtb_ot_end[] are created by cmd_dt_S_dtb
* in scripts/Makefile.lib
*/
#define OVERLAY_INFO_EXTERN(name) \
extern uint8_t __dtb_##name##_begin[]; \
extern uint8_t __dtb_##name##_end[]
#define OVERLAY_INFO(name, expected) \
{ .dtb_begin = __dtb_##name##_begin, \
.dtb_end = __dtb_##name##_end, \
.expected_result = expected, \
}
struct overlay_info {
uint8_t *dtb_begin;
uint8_t *dtb_end;
void *data;
struct device_node *np_overlay;
int expected_result;
int overlay_id;
};
OVERLAY_INFO_EXTERN(overlay_base);
OVERLAY_INFO_EXTERN(overlay);
OVERLAY_INFO_EXTERN(overlay_bad_phandle);
#ifdef CONFIG_OF_OVERLAY
/* order of entries is hard-coded into users of overlays[] */
static struct overlay_info overlays[] = {
OVERLAY_INFO(overlay_base, -9999),
OVERLAY_INFO(overlay, 0),
OVERLAY_INFO(overlay_bad_phandle, -EINVAL),
{}
};
static struct device_node *overlay_base_root;
/*
* Create base device tree for the overlay unittest.
*
* This is called from very early boot code.
*
* Do as much as possible the same way as done in __unflatten_device_tree
* and other early boot steps for the normal FDT so that the overlay base
* unflattened tree will have the same characteristics as the real tree
* (such as having memory allocated by the early allocator). The goal
* is to test "the real thing" as much as possible, and test "test setup
* code" as little as possible.
*
* Have to stop before resolving phandles, because that uses kmalloc.
*/
void __init unittest_unflatten_overlay_base(void)
{
struct overlay_info *info;
u32 data_size;
u32 size;
info = &overlays[0];
if (info->expected_result != -9999) {
pr_err("No dtb 'overlay_base' to attach\n");
return;
}
data_size = info->dtb_end - info->dtb_begin;
if (!data_size) {
pr_err("No dtb 'overlay_base' to attach\n");
return;
}
size = fdt_totalsize(info->dtb_begin);
if (size != data_size) {
pr_err("dtb 'overlay_base' header totalsize != actual size");
return;
}
info->data = early_init_dt_alloc_memory_arch(size,
roundup_pow_of_two(FDT_V17_SIZE));
if (!info->data) {
pr_err("alloc for dtb 'overlay_base' failed");
return;
}
memcpy(info->data, info->dtb_begin, size);
__unflatten_device_tree(info->data, NULL, &info->np_overlay,
early_init_dt_alloc_memory_arch, true);
overlay_base_root = info->np_overlay;
}
/*
* The purpose of of_unittest_overlay_data_add is to add an
* overlay in the normal fashion. This is a test of the whole
* picture, instead of testing individual elements.
*
* A secondary purpose is to be able to verify that the contents of
* /proc/device-tree/ contains the updated structure and values from
* the overlay. That must be verified separately in user space.
*
* Return 0 on unexpected error.
*/
static int __init overlay_data_add(int onum)
{
struct overlay_info *info;
int k;
int ret;
u32 size;
u32 size_from_header;
for (k = 0, info = overlays; info; info++, k++) {
if (k == onum)
break;
}
if (onum > k)
return 0;
size = info->dtb_end - info->dtb_begin;
if (!size) {
pr_err("no overlay to attach, %d\n", onum);
ret = 0;
}
size_from_header = fdt_totalsize(info->dtb_begin);
if (size_from_header != size) {
pr_err("overlay header totalsize != actual size, %d", onum);
return 0;
}
/*
* Must create permanent copy of FDT because of_fdt_unflatten_tree()
* will create pointers to the passed in FDT in the EDT.
*/
info->data = kmemdup(info->dtb_begin, size, GFP_KERNEL);
if (!info->data) {
pr_err("unable to allocate memory for data, %d\n", onum);
return 0;
}
of_fdt_unflatten_tree(info->data, NULL, &info->np_overlay);
if (!info->np_overlay) {
pr_err("unable to unflatten overlay, %d\n", onum);
ret = 0;
goto out_free_data;
}
of_node_set_flag(info->np_overlay, OF_DETACHED);
ret = of_resolve_phandles(info->np_overlay);
if (ret) {
pr_err("resolve ot phandles (ret=%d), %d\n", ret, onum);
goto out_free_np_overlay;
}
ret = of_overlay_create(info->np_overlay);
if (ret < 0) {
pr_err("of_overlay_create() (ret=%d), %d\n", ret, onum);
goto out_free_np_overlay;
} else {
info->overlay_id = ret;
ret = 0;
}
pr_debug("__dtb_overlay_begin applied, overlay id %d\n", ret);
goto out;
out_free_np_overlay:
/*
* info->np_overlay is the unflattened device tree
* It has not been spliced into the live tree.
*/
/* todo: function to free unflattened device tree */
out_free_data:
kfree(info->data);
out:
return (ret == info->expected_result);
}
/*
* The purpose of of_unittest_overlay_high_level is to add an overlay
* in the normal fashion. This is a test of the whole picture,
* instead of individual elements.
*
* The first part of the function is _not_ normal overlay usage; it is
* finishing splicing the base overlay device tree into the live tree.
*/
static __init void of_unittest_overlay_high_level(void)
{
struct device_node *last_sibling;
struct device_node *np;
struct device_node *of_symbols;
struct device_node *overlay_base_symbols;
struct device_node **pprev;
struct property *prop;
int ret;
if (!overlay_base_root) {
unittest(0, "overlay_base_root not initialized\n");
return;
}
/*
* Could not fixup phandles in unittest_unflatten_overlay_base()
* because kmalloc() was not yet available.
*/
of_resolve_phandles(overlay_base_root);
/*
* do not allow overlay_base to duplicate any node already in
* tree, this greatly simplifies the code
*/
/*
* remove overlay_base_root node "__local_fixups", after
* being used by of_resolve_phandles()
*/
pprev = &overlay_base_root->child;
for (np = overlay_base_root->child; np; np = np->sibling) {
if (!of_node_cmp(np->name, "__local_fixups__")) {
*pprev = np->sibling;
break;
}
pprev = &np->sibling;
}
/* remove overlay_base_root node "__symbols__" if in live tree */
of_symbols = of_get_child_by_name(of_root, "__symbols__");
if (of_symbols) {
/* will have to graft properties from node into live tree */
pprev = &overlay_base_root->child;
for (np = overlay_base_root->child; np; np = np->sibling) {
if (!of_node_cmp(np->name, "__symbols__")) {
overlay_base_symbols = np;
*pprev = np->sibling;
break;
}
pprev = &np->sibling;
}
}
for (np = overlay_base_root->child; np; np = np->sibling) {
if (of_get_child_by_name(of_root, np->name)) {
unittest(0, "illegal node name in overlay_base %s",
np->name);
return;
}
}
/*
* overlay 'overlay_base' is not allowed to have root
* properties, so only need to splice nodes into main device tree.
*
* root node of *overlay_base_root will not be freed, it is lost
* memory.
*/
for (np = overlay_base_root->child; np; np = np->sibling)
np->parent = of_root;
mutex_lock(&of_mutex);
for (last_sibling = np = of_root->child; np; np = np->sibling)
last_sibling = np;
if (last_sibling)
last_sibling->sibling = overlay_base_root->child;
else
of_root->child = overlay_base_root->child;
for_each_of_allnodes_from(overlay_base_root, np)
__of_attach_node_sysfs(np);
if (of_symbols) {
for_each_property_of_node(overlay_base_symbols, prop) {
ret = __of_add_property(of_symbols, prop);
if (ret) {
unittest(0,
"duplicate property '%s' in overlay_base node __symbols__",
prop->name);
goto err_unlock;
}
ret = __of_add_property_sysfs(of_symbols, prop);
if (ret) {
unittest(0,
"unable to add property '%s' in overlay_base node __symbols__ to sysfs",
prop->name);
goto err_unlock;
}
}
}
mutex_unlock(&of_mutex);
/* now do the normal overlay usage test */
unittest(overlay_data_add(1),
"Adding overlay 'overlay' failed\n");
unittest(overlay_data_add(2),
"Adding overlay 'overlay_bad_phandle' failed\n");
return;
err_unlock:
mutex_unlock(&of_mutex);
}
#else
static inline __init void of_unittest_overlay_high_level(void) {}
#endif
static int __init of_unittest(void) static int __init of_unittest(void)
{ {
struct device_node *np; struct device_node *np;
...@@ -1962,6 +2281,8 @@ static int __init of_unittest(void) ...@@ -1962,6 +2281,8 @@ static int __init of_unittest(void)
/* Double check linkage after removing testcase data */ /* Double check linkage after removing testcase data */
of_unittest_check_tree_linkage(); of_unittest_check_tree_linkage();
of_unittest_overlay_high_level();
pr_info("end of unittest - %i passed, %i failed\n", pr_info("end of unittest - %i passed, %i failed\n",
unittest_results.passed, unittest_results.failed); unittest_results.passed, unittest_results.failed);
......
...@@ -224,10 +224,7 @@ static int serdev_drv_remove(struct device *dev) ...@@ -224,10 +224,7 @@ static int serdev_drv_remove(struct device *dev)
static ssize_t modalias_show(struct device *dev, static ssize_t modalias_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2); return of_device_modalias(dev, buf, PAGE_SIZE);
buf[len] = '\n';
buf[len+1] = 0;
return len+1;
} }
static struct device_attribute serdev_device_attrs[] = { static struct device_attribute serdev_device_attrs[] = {
......
...@@ -107,7 +107,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, ...@@ -107,7 +107,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
int len; int len;
struct ulpi *ulpi = to_ulpi_dev(dev); struct ulpi *ulpi = to_ulpi_dev(dev);
len = of_device_get_modalias(dev, buf, PAGE_SIZE - 1); len = of_device_modalias(dev, buf, PAGE_SIZE);
if (len != -ENODEV) if (len != -ENODEV)
return len; return len;
......
...@@ -34,8 +34,7 @@ extern void of_device_unregister(struct platform_device *ofdev); ...@@ -34,8 +34,7 @@ extern void of_device_unregister(struct platform_device *ofdev);
extern const void *of_device_get_match_data(const struct device *dev); extern const void *of_device_get_match_data(const struct device *dev);
extern ssize_t of_device_get_modalias(struct device *dev, extern ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len);
char *str, ssize_t len);
extern int of_device_request_module(struct device *dev); extern int of_device_request_module(struct device *dev);
extern void of_device_uevent(struct device *dev, struct kobj_uevent_env *env); extern void of_device_uevent(struct device *dev, struct kobj_uevent_env *env);
...@@ -72,8 +71,8 @@ static inline const void *of_device_get_match_data(const struct device *dev) ...@@ -72,8 +71,8 @@ static inline const void *of_device_get_match_data(const struct device *dev)
return NULL; return NULL;
} }
static inline int of_device_get_modalias(struct device *dev, static inline int of_device_modalias(struct device *dev,
char *str, ssize_t len) char *str, ssize_t len)
{ {
return -ENODEV; return -ENODEV;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/of.h> #include <linux/of.h>
typedef int (*of_irq_init_cb_t)(struct device_node *, struct device_node *); typedef int const (*of_irq_init_cb_t)(struct device_node *, struct device_node *);
/* /*
* Workarounds only applied to 32bit powermac machines * Workarounds only applied to 32bit powermac machines
......
...@@ -280,9 +280,21 @@ DTC ?= $(objtree)/scripts/dtc/dtc ...@@ -280,9 +280,21 @@ DTC ?= $(objtree)/scripts/dtc/dtc
# Disable noisy checks by default # Disable noisy checks by default
ifeq ($(KBUILD_ENABLE_EXTRA_GCC_CHECKS),) ifeq ($(KBUILD_ENABLE_EXTRA_GCC_CHECKS),)
DTC_FLAGS += -Wno-unit_address_vs_reg DTC_FLAGS += -Wno-unit_address_vs_reg \
-Wno-simple_bus_reg \
-Wno-unit_address_format \
-Wno-pci_bridge \
-Wno-pci_device_bus_num \
-Wno-pci_device_reg
endif endif
ifeq ($(KBUILD_ENABLE_EXTRA_GCC_CHECKS),2)
DTC_FLAGS += -Wnode_name_chars_strict \
-Wproperty_name_chars_strict
endif
DTC_FLAGS += $(DTC_FLAGS_$(basetarget))
# Generate an assembly file to wrap the output of the device tree compiler # Generate an assembly file to wrap the output of the device tree compiler
quiet_cmd_dt_S_dtb= DTB $@ quiet_cmd_dt_S_dtb= DTB $@
cmd_dt_S_dtb= \ cmd_dt_S_dtb= \
......
...@@ -72,17 +72,16 @@ struct check { ...@@ -72,17 +72,16 @@ struct check {
#define CHECK(_nm, _fn, _d, ...) \ #define CHECK(_nm, _fn, _d, ...) \
CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__) CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__)
#ifdef __GNUC__ static inline void PRINTF(3, 4) check_msg(struct check *c, struct dt_info *dti,
static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); const char *fmt, ...)
#endif
static inline void check_msg(struct check *c, const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
if ((c->warn && (quiet < 1)) if ((c->warn && (quiet < 1))
|| (c->error && (quiet < 2))) { || (c->error && (quiet < 2))) {
fprintf(stderr, "%s (%s): ", fprintf(stderr, "%s: %s (%s): ",
strcmp(dti->outname, "-") ? dti->outname : "<stdout>",
(c->error) ? "ERROR" : "Warning", c->name); (c->error) ? "ERROR" : "Warning", c->name);
vfprintf(stderr, fmt, ap); vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
...@@ -90,11 +89,11 @@ static inline void check_msg(struct check *c, const char *fmt, ...) ...@@ -90,11 +89,11 @@ static inline void check_msg(struct check *c, const char *fmt, ...)
va_end(ap); va_end(ap);
} }
#define FAIL(c, ...) \ #define FAIL(c, dti, ...) \
do { \ do { \
TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \ TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
(c)->status = FAILED; \ (c)->status = FAILED; \
check_msg((c), __VA_ARGS__); \ check_msg((c), dti, __VA_ARGS__); \
} while (0) } while (0)
static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node) static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node)
...@@ -127,7 +126,7 @@ static bool run_check(struct check *c, struct dt_info *dti) ...@@ -127,7 +126,7 @@ static bool run_check(struct check *c, struct dt_info *dti)
error = error || run_check(prq, dti); error = error || run_check(prq, dti);
if (prq->status != PASSED) { if (prq->status != PASSED) {
c->status = PREREQ; c->status = PREREQ;
check_msg(c, "Failed prerequisite '%s'", check_msg(c, dti, "Failed prerequisite '%s'",
c->prereq[i]->name); c->prereq[i]->name);
} }
} }
...@@ -157,7 +156,7 @@ static bool run_check(struct check *c, struct dt_info *dti) ...@@ -157,7 +156,7 @@ static bool run_check(struct check *c, struct dt_info *dti)
static inline void check_always_fail(struct check *c, struct dt_info *dti, static inline void check_always_fail(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
FAIL(c, "always_fail check"); FAIL(c, dti, "always_fail check");
} }
CHECK(always_fail, check_always_fail, NULL); CHECK(always_fail, check_always_fail, NULL);
...@@ -172,7 +171,7 @@ static void check_is_string(struct check *c, struct dt_info *dti, ...@@ -172,7 +171,7 @@ static void check_is_string(struct check *c, struct dt_info *dti,
return; /* Not present, assumed ok */ return; /* Not present, assumed ok */
if (!data_is_one_string(prop->val)) if (!data_is_one_string(prop->val))
FAIL(c, "\"%s\" property in %s is not a string", FAIL(c, dti, "\"%s\" property in %s is not a string",
propname, node->fullpath); propname, node->fullpath);
} }
#define WARNING_IF_NOT_STRING(nm, propname) \ #define WARNING_IF_NOT_STRING(nm, propname) \
...@@ -191,7 +190,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti, ...@@ -191,7 +190,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti,
return; /* Not present, assumed ok */ return; /* Not present, assumed ok */
if (prop->val.len != sizeof(cell_t)) if (prop->val.len != sizeof(cell_t))
FAIL(c, "\"%s\" property in %s is not a single cell", FAIL(c, dti, "\"%s\" property in %s is not a single cell",
propname, node->fullpath); propname, node->fullpath);
} }
#define WARNING_IF_NOT_CELL(nm, propname) \ #define WARNING_IF_NOT_CELL(nm, propname) \
...@@ -213,7 +212,7 @@ static void check_duplicate_node_names(struct check *c, struct dt_info *dti, ...@@ -213,7 +212,7 @@ static void check_duplicate_node_names(struct check *c, struct dt_info *dti,
child2; child2;
child2 = child2->next_sibling) child2 = child2->next_sibling)
if (streq(child->name, child2->name)) if (streq(child->name, child2->name))
FAIL(c, "Duplicate node name %s", FAIL(c, dti, "Duplicate node name %s",
child->fullpath); child->fullpath);
} }
ERROR(duplicate_node_names, check_duplicate_node_names, NULL); ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
...@@ -228,7 +227,7 @@ static void check_duplicate_property_names(struct check *c, struct dt_info *dti, ...@@ -228,7 +227,7 @@ static void check_duplicate_property_names(struct check *c, struct dt_info *dti,
if (prop2->deleted) if (prop2->deleted)
continue; continue;
if (streq(prop->name, prop2->name)) if (streq(prop->name, prop2->name))
FAIL(c, "Duplicate property name %s in %s", FAIL(c, dti, "Duplicate property name %s in %s",
prop->name, node->fullpath); prop->name, node->fullpath);
} }
} }
...@@ -239,6 +238,7 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL); ...@@ -239,6 +238,7 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define DIGITS "0123456789" #define DIGITS "0123456789"
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-" #define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
#define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
static void check_node_name_chars(struct check *c, struct dt_info *dti, static void check_node_name_chars(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
...@@ -246,16 +246,27 @@ static void check_node_name_chars(struct check *c, struct dt_info *dti, ...@@ -246,16 +246,27 @@ static void check_node_name_chars(struct check *c, struct dt_info *dti,
int n = strspn(node->name, c->data); int n = strspn(node->name, c->data);
if (n < strlen(node->name)) if (n < strlen(node->name))
FAIL(c, "Bad character '%c' in node %s", FAIL(c, dti, "Bad character '%c' in node %s",
node->name[n], node->fullpath); node->name[n], node->fullpath);
} }
ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@"); ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
struct node *node)
{
int n = strspn(node->name, c->data);
if (n < node->basenamelen)
FAIL(c, dti, "Character '%c' not recommended in node %s",
node->name[n], node->fullpath);
}
CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT);
static void check_node_name_format(struct check *c, struct dt_info *dti, static void check_node_name_format(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
if (strchr(get_unitname(node), '@')) if (strchr(get_unitname(node), '@'))
FAIL(c, "Node %s has multiple '@' characters in name", FAIL(c, dti, "Node %s has multiple '@' characters in name",
node->fullpath); node->fullpath);
} }
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars); ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
...@@ -274,11 +285,11 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti, ...@@ -274,11 +285,11 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
if (prop) { if (prop) {
if (!unitname[0]) if (!unitname[0])
FAIL(c, "Node %s has a reg or ranges property, but no unit name", FAIL(c, dti, "Node %s has a reg or ranges property, but no unit name",
node->fullpath); node->fullpath);
} else { } else {
if (unitname[0]) if (unitname[0])
FAIL(c, "Node %s has a unit name, but no reg property", FAIL(c, dti, "Node %s has a unit name, but no reg property",
node->fullpath); node->fullpath);
} }
} }
...@@ -293,12 +304,44 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti, ...@@ -293,12 +304,44 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
int n = strspn(prop->name, c->data); int n = strspn(prop->name, c->data);
if (n < strlen(prop->name)) if (n < strlen(prop->name))
FAIL(c, "Bad character '%c' in property name \"%s\", node %s", FAIL(c, dti, "Bad character '%c' in property name \"%s\", node %s",
prop->name[n], prop->name, node->fullpath); prop->name[n], prop->name, node->fullpath);
} }
} }
ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS); ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
static void check_property_name_chars_strict(struct check *c,
struct dt_info *dti,
struct node *node)
{
struct property *prop;
for_each_property(node, prop) {
const char *name = prop->name;
int n = strspn(name, c->data);
if (n == strlen(prop->name))
continue;
/* Certain names are whitelisted */
if (streq(name, "device_type"))
continue;
/*
* # is only allowed at the beginning of property names not counting
* the vendor prefix.
*/
if (name[n] == '#' && ((n == 0) || (name[n-1] == ','))) {
name += n + 1;
n = strspn(name, c->data);
}
if (n < strlen(name))
FAIL(c, dti, "Character '%c' not recommended in property name \"%s\", node %s",
name[n], prop->name, node->fullpath);
}
}
CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT);
#define DESCLABEL_FMT "%s%s%s%s%s" #define DESCLABEL_FMT "%s%s%s%s%s"
#define DESCLABEL_ARGS(node,prop,mark) \ #define DESCLABEL_ARGS(node,prop,mark) \
((mark) ? "value of " : ""), \ ((mark) ? "value of " : ""), \
...@@ -327,7 +370,7 @@ static void check_duplicate_label(struct check *c, struct dt_info *dti, ...@@ -327,7 +370,7 @@ static void check_duplicate_label(struct check *c, struct dt_info *dti,
return; return;
if ((othernode != node) || (otherprop != prop) || (othermark != mark)) if ((othernode != node) || (otherprop != prop) || (othermark != mark))
FAIL(c, "Duplicate label '%s' on " DESCLABEL_FMT FAIL(c, dti, "Duplicate label '%s' on " DESCLABEL_FMT
" and " DESCLABEL_FMT, " and " DESCLABEL_FMT,
label, DESCLABEL_ARGS(node, prop, mark), label, DESCLABEL_ARGS(node, prop, mark),
DESCLABEL_ARGS(othernode, otherprop, othermark)); DESCLABEL_ARGS(othernode, otherprop, othermark));
...@@ -367,7 +410,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti, ...@@ -367,7 +410,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
return 0; return 0;
if (prop->val.len != sizeof(cell_t)) { if (prop->val.len != sizeof(cell_t)) {
FAIL(c, "%s has bad length (%d) %s property", FAIL(c, dti, "%s has bad length (%d) %s property",
node->fullpath, prop->val.len, prop->name); node->fullpath, prop->val.len, prop->name);
return 0; return 0;
} }
...@@ -379,7 +422,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti, ...@@ -379,7 +422,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
/* "Set this node's phandle equal to some /* "Set this node's phandle equal to some
* other node's phandle". That's nonsensical * other node's phandle". That's nonsensical
* by construction. */ { * by construction. */ {
FAIL(c, "%s in %s is a reference to another node", FAIL(c, dti, "%s in %s is a reference to another node",
prop->name, node->fullpath); prop->name, node->fullpath);
} }
/* But setting this node's phandle equal to its own /* But setting this node's phandle equal to its own
...@@ -393,7 +436,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti, ...@@ -393,7 +436,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
phandle = propval_cell(prop); phandle = propval_cell(prop);
if ((phandle == 0) || (phandle == -1)) { if ((phandle == 0) || (phandle == -1)) {
FAIL(c, "%s has bad value (0x%x) in %s property", FAIL(c, dti, "%s has bad value (0x%x) in %s property",
node->fullpath, phandle, prop->name); node->fullpath, phandle, prop->name);
return 0; return 0;
} }
...@@ -420,7 +463,7 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti, ...@@ -420,7 +463,7 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti,
return; return;
if (linux_phandle && phandle && (phandle != linux_phandle)) if (linux_phandle && phandle && (phandle != linux_phandle))
FAIL(c, "%s has mismatching 'phandle' and 'linux,phandle'" FAIL(c, dti, "%s has mismatching 'phandle' and 'linux,phandle'"
" properties", node->fullpath); " properties", node->fullpath);
if (linux_phandle && !phandle) if (linux_phandle && !phandle)
...@@ -428,7 +471,7 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti, ...@@ -428,7 +471,7 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti,
other = get_node_by_phandle(root, phandle); other = get_node_by_phandle(root, phandle);
if (other && (other != node)) { if (other && (other != node)) {
FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)", FAIL(c, dti, "%s has duplicated phandle 0x%x (seen before at %s)",
node->fullpath, phandle, other->fullpath); node->fullpath, phandle, other->fullpath);
return; return;
} }
...@@ -453,7 +496,7 @@ static void check_name_properties(struct check *c, struct dt_info *dti, ...@@ -453,7 +496,7 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
if ((prop->val.len != node->basenamelen+1) if ((prop->val.len != node->basenamelen+1)
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) { || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead" FAIL(c, dti, "\"name\" property in %s is incorrect (\"%s\" instead"
" of base node name)", node->fullpath, prop->val.val); " of base node name)", node->fullpath, prop->val.val);
} else { } else {
/* The name property is correct, and therefore redundant. /* The name property is correct, and therefore redundant.
...@@ -488,16 +531,16 @@ static void fixup_phandle_references(struct check *c, struct dt_info *dti, ...@@ -488,16 +531,16 @@ static void fixup_phandle_references(struct check *c, struct dt_info *dti,
refnode = get_node_by_ref(dt, m->ref); refnode = get_node_by_ref(dt, m->ref);
if (! refnode) { if (! refnode) {
if (!(dti->dtsflags & DTSF_PLUGIN)) if (!(dti->dtsflags & DTSF_PLUGIN))
FAIL(c, "Reference to non-existent node or " FAIL(c, dti, "Reference to non-existent node or "
"label \"%s\"\n", m->ref); "label \"%s\"\n", m->ref);
else /* mark the entry as unresolved */ else /* mark the entry as unresolved */
*((cell_t *)(prop->val.val + m->offset)) = *((fdt32_t *)(prop->val.val + m->offset)) =
cpu_to_fdt32(0xffffffff); cpu_to_fdt32(0xffffffff);
continue; continue;
} }
phandle = get_node_phandle(dt, refnode); phandle = get_node_phandle(dt, refnode);
*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); *((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
} }
} }
} }
...@@ -520,7 +563,7 @@ static void fixup_path_references(struct check *c, struct dt_info *dti, ...@@ -520,7 +563,7 @@ static void fixup_path_references(struct check *c, struct dt_info *dti,
refnode = get_node_by_ref(dt, m->ref); refnode = get_node_by_ref(dt, m->ref);
if (!refnode) { if (!refnode) {
FAIL(c, "Reference to non-existent node or label \"%s\"\n", FAIL(c, dti, "Reference to non-existent node or label \"%s\"\n",
m->ref); m->ref);
continue; continue;
} }
...@@ -579,19 +622,19 @@ static void check_reg_format(struct check *c, struct dt_info *dti, ...@@ -579,19 +622,19 @@ static void check_reg_format(struct check *c, struct dt_info *dti,
return; /* No "reg", that's fine */ return; /* No "reg", that's fine */
if (!node->parent) { if (!node->parent) {
FAIL(c, "Root node has a \"reg\" property"); FAIL(c, dti, "Root node has a \"reg\" property");
return; return;
} }
if (prop->val.len == 0) if (prop->val.len == 0)
FAIL(c, "\"reg\" property in %s is empty", node->fullpath); FAIL(c, dti, "\"reg\" property in %s is empty", node->fullpath);
addr_cells = node_addr_cells(node->parent); addr_cells = node_addr_cells(node->parent);
size_cells = node_size_cells(node->parent); size_cells = node_size_cells(node->parent);
entrylen = (addr_cells + size_cells) * sizeof(cell_t); entrylen = (addr_cells + size_cells) * sizeof(cell_t);
if (!entrylen || (prop->val.len % entrylen) != 0) if (!entrylen || (prop->val.len % entrylen) != 0)
FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) " FAIL(c, dti, "\"reg\" property in %s has invalid length (%d bytes) "
"(#address-cells == %d, #size-cells == %d)", "(#address-cells == %d, #size-cells == %d)",
node->fullpath, prop->val.len, addr_cells, size_cells); node->fullpath, prop->val.len, addr_cells, size_cells);
} }
...@@ -608,7 +651,7 @@ static void check_ranges_format(struct check *c, struct dt_info *dti, ...@@ -608,7 +651,7 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
return; return;
if (!node->parent) { if (!node->parent) {
FAIL(c, "Root node has a \"ranges\" property"); FAIL(c, dti, "Root node has a \"ranges\" property");
return; return;
} }
...@@ -620,17 +663,17 @@ static void check_ranges_format(struct check *c, struct dt_info *dti, ...@@ -620,17 +663,17 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
if (prop->val.len == 0) { if (prop->val.len == 0) {
if (p_addr_cells != c_addr_cells) if (p_addr_cells != c_addr_cells)
FAIL(c, "%s has empty \"ranges\" property but its " FAIL(c, dti, "%s has empty \"ranges\" property but its "
"#address-cells (%d) differs from %s (%d)", "#address-cells (%d) differs from %s (%d)",
node->fullpath, c_addr_cells, node->parent->fullpath, node->fullpath, c_addr_cells, node->parent->fullpath,
p_addr_cells); p_addr_cells);
if (p_size_cells != c_size_cells) if (p_size_cells != c_size_cells)
FAIL(c, "%s has empty \"ranges\" property but its " FAIL(c, dti, "%s has empty \"ranges\" property but its "
"#size-cells (%d) differs from %s (%d)", "#size-cells (%d) differs from %s (%d)",
node->fullpath, c_size_cells, node->parent->fullpath, node->fullpath, c_size_cells, node->parent->fullpath,
p_size_cells); p_size_cells);
} else if ((prop->val.len % entrylen) != 0) { } else if ((prop->val.len % entrylen) != 0) {
FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) " FAIL(c, dti, "\"ranges\" property in %s has invalid length (%d bytes) "
"(parent #address-cells == %d, child #address-cells == %d, " "(parent #address-cells == %d, child #address-cells == %d, "
"#size-cells == %d)", node->fullpath, prop->val.len, "#size-cells == %d)", node->fullpath, prop->val.len,
p_addr_cells, c_addr_cells, c_size_cells); p_addr_cells, c_addr_cells, c_size_cells);
...@@ -638,6 +681,229 @@ static void check_ranges_format(struct check *c, struct dt_info *dti, ...@@ -638,6 +681,229 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
} }
WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells); WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
static const struct bus_type pci_bus = {
.name = "PCI",
};
static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *node)
{
struct property *prop;
cell_t *cells;
prop = get_property(node, "device_type");
if (!prop || !streq(prop->val.val, "pci"))
return;
node->bus = &pci_bus;
if (!strneq(node->name, "pci", node->basenamelen) &&
!strneq(node->name, "pcie", node->basenamelen))
FAIL(c, dti, "Node %s node name is not \"pci\" or \"pcie\"",
node->fullpath);
prop = get_property(node, "ranges");
if (!prop)
FAIL(c, dti, "Node %s missing ranges for PCI bridge (or not a bridge)",
node->fullpath);
if (node_addr_cells(node) != 3)
FAIL(c, dti, "Node %s incorrect #address-cells for PCI bridge",
node->fullpath);
if (node_size_cells(node) != 2)
FAIL(c, dti, "Node %s incorrect #size-cells for PCI bridge",
node->fullpath);
prop = get_property(node, "bus-range");
if (!prop) {
FAIL(c, dti, "Node %s missing bus-range for PCI bridge",
node->fullpath);
return;
}
if (prop->val.len != (sizeof(cell_t) * 2)) {
FAIL(c, dti, "Node %s bus-range must be 2 cells",
node->fullpath);
return;
}
cells = (cell_t *)prop->val.val;
if (fdt32_to_cpu(cells[0]) > fdt32_to_cpu(cells[1]))
FAIL(c, dti, "Node %s bus-range 1st cell must be less than or equal to 2nd cell",
node->fullpath);
if (fdt32_to_cpu(cells[1]) > 0xff)
FAIL(c, dti, "Node %s bus-range maximum bus number must be less than 256",
node->fullpath);
}
WARNING(pci_bridge, check_pci_bridge, NULL,
&device_type_is_string, &addr_size_cells);
static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struct node *node)
{
struct property *prop;
unsigned int bus_num, min_bus, max_bus;
cell_t *cells;
if (!node->parent || (node->parent->bus != &pci_bus))
return;
prop = get_property(node, "reg");
if (!prop)
return;
cells = (cell_t *)prop->val.val;
bus_num = (fdt32_to_cpu(cells[0]) & 0x00ff0000) >> 16;
prop = get_property(node->parent, "bus-range");
if (!prop) {
min_bus = max_bus = 0;
} else {
cells = (cell_t *)prop->val.val;
min_bus = fdt32_to_cpu(cells[0]);
max_bus = fdt32_to_cpu(cells[0]);
}
if ((bus_num < min_bus) || (bus_num > max_bus))
FAIL(c, dti, "Node %s PCI bus number %d out of range, expected (%d - %d)",
node->fullpath, bus_num, min_bus, max_bus);
}
WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, &reg_format, &pci_bridge);
static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct node *node)
{
struct property *prop;
const char *unitname = get_unitname(node);
char unit_addr[5];
unsigned int dev, func, reg;
cell_t *cells;
if (!node->parent || (node->parent->bus != &pci_bus))
return;
prop = get_property(node, "reg");
if (!prop) {
FAIL(c, dti, "Node %s missing PCI reg property", node->fullpath);
return;
}
cells = (cell_t *)prop->val.val;
if (cells[1] || cells[2])
FAIL(c, dti, "Node %s PCI reg config space address cells 2 and 3 must be 0",
node->fullpath);
reg = fdt32_to_cpu(cells[0]);
dev = (reg & 0xf800) >> 11;
func = (reg & 0x700) >> 8;
if (reg & 0xff000000)
FAIL(c, dti, "Node %s PCI reg address is not configuration space",
node->fullpath);
if (reg & 0x000000ff)
FAIL(c, dti, "Node %s PCI reg config space address register number must be 0",
node->fullpath);
if (func == 0) {
snprintf(unit_addr, sizeof(unit_addr), "%x", dev);
if (streq(unitname, unit_addr))
return;
}
snprintf(unit_addr, sizeof(unit_addr), "%x,%x", dev, func);
if (streq(unitname, unit_addr))
return;
FAIL(c, dti, "Node %s PCI unit address format error, expected \"%s\"",
node->fullpath, unit_addr);
}
WARNING(pci_device_reg, check_pci_device_reg, NULL, &reg_format, &pci_bridge);
static const struct bus_type simple_bus = {
.name = "simple-bus",
};
static bool node_is_compatible(struct node *node, const char *compat)
{
struct property *prop;
const char *str, *end;
prop = get_property(node, "compatible");
if (!prop)
return false;
for (str = prop->val.val, end = str + prop->val.len; str < end;
str += strnlen(str, end - str) + 1) {
if (strneq(str, compat, end - str))
return true;
}
return false;
}
static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
{
if (node_is_compatible(node, "simple-bus"))
node->bus = &simple_bus;
}
WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells);
static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
{
struct property *prop;
const char *unitname = get_unitname(node);
char unit_addr[17];
unsigned int size;
uint64_t reg = 0;
cell_t *cells = NULL;
if (!node->parent || (node->parent->bus != &simple_bus))
return;
prop = get_property(node, "reg");
if (prop)
cells = (cell_t *)prop->val.val;
else {
prop = get_property(node, "ranges");
if (prop && prop->val.len)
/* skip of child address */
cells = ((cell_t *)prop->val.val) + node_addr_cells(node);
}
if (!cells) {
if (node->parent->parent && !(node->bus == &simple_bus))
FAIL(c, dti, "Node %s missing or empty reg/ranges property", node->fullpath);
return;
}
size = node_addr_cells(node->parent);
while (size--)
reg = (reg << 32) | fdt32_to_cpu(*(cells++));
snprintf(unit_addr, sizeof(unit_addr), "%lx", reg);
if (!streq(unitname, unit_addr))
FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"",
node->fullpath, unit_addr);
}
WARNING(simple_bus_reg, check_simple_bus_reg, NULL, &reg_format, &simple_bus_bridge);
static void check_unit_address_format(struct check *c, struct dt_info *dti,
struct node *node)
{
const char *unitname = get_unitname(node);
if (node->parent && node->parent->bus)
return;
if (!unitname[0])
return;
if (!strncmp(unitname, "0x", 2)) {
FAIL(c, dti, "Node %s unit name should not have leading \"0x\"",
node->fullpath);
/* skip over 0x for next test */
unitname += 2;
}
if (unitname[0] == '0' && isxdigit(unitname[1]))
FAIL(c, dti, "Node %s unit name should not have leading 0s",
node->fullpath);
}
WARNING(unit_address_format, check_unit_address_format, NULL,
&node_name_format, &pci_bridge, &simple_bus_bridge);
/* /*
* Style checks * Style checks
*/ */
...@@ -656,11 +922,11 @@ static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti, ...@@ -656,11 +922,11 @@ static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti,
return; return;
if (node->parent->addr_cells == -1) if (node->parent->addr_cells == -1)
FAIL(c, "Relying on default #address-cells value for %s", FAIL(c, dti, "Relying on default #address-cells value for %s",
node->fullpath); node->fullpath);
if (node->parent->size_cells == -1) if (node->parent->size_cells == -1)
FAIL(c, "Relying on default #size-cells value for %s", FAIL(c, dti, "Relying on default #size-cells value for %s",
node->fullpath); node->fullpath);
} }
WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL, WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
...@@ -684,7 +950,7 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c, ...@@ -684,7 +950,7 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
prop = get_property(chosen, "interrupt-controller"); prop = get_property(chosen, "interrupt-controller");
if (prop) if (prop)
FAIL(c, "/chosen has obsolete \"interrupt-controller\" " FAIL(c, dti, "/chosen has obsolete \"interrupt-controller\" "
"property"); "property");
} }
WARNING(obsolete_chosen_interrupt_controller, WARNING(obsolete_chosen_interrupt_controller,
...@@ -703,9 +969,20 @@ static struct check *check_table[] = { ...@@ -703,9 +969,20 @@ static struct check *check_table[] = {
&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell, &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
&device_type_is_string, &model_is_string, &status_is_string, &device_type_is_string, &model_is_string, &status_is_string,
&property_name_chars_strict,
&node_name_chars_strict,
&addr_size_cells, &reg_format, &ranges_format, &addr_size_cells, &reg_format, &ranges_format,
&unit_address_vs_reg, &unit_address_vs_reg,
&unit_address_format,
&pci_bridge,
&pci_device_reg,
&pci_device_bus_num,
&simple_bus_bridge,
&simple_bus_reg,
&avoid_default_addr_size, &avoid_default_addr_size,
&obsolete_chosen_interrupt_controller, &obsolete_chosen_interrupt_controller,
......
...@@ -171,9 +171,9 @@ struct data data_merge(struct data d1, struct data d2) ...@@ -171,9 +171,9 @@ struct data data_merge(struct data d1, struct data d2)
struct data data_append_integer(struct data d, uint64_t value, int bits) struct data data_append_integer(struct data d, uint64_t value, int bits)
{ {
uint8_t value_8; uint8_t value_8;
uint16_t value_16; fdt16_t value_16;
uint32_t value_32; fdt32_t value_32;
uint64_t value_64; fdt64_t value_64;
switch (bits) { switch (bits) {
case 8: case 8:
...@@ -197,14 +197,14 @@ struct data data_append_integer(struct data d, uint64_t value, int bits) ...@@ -197,14 +197,14 @@ struct data data_append_integer(struct data d, uint64_t value, int bits)
} }
} }
struct data data_append_re(struct data d, const struct fdt_reserve_entry *re) struct data data_append_re(struct data d, uint64_t address, uint64_t size)
{ {
struct fdt_reserve_entry bere; struct fdt_reserve_entry re;
bere.address = cpu_to_fdt64(re->address); re.address = cpu_to_fdt64(address);
bere.size = cpu_to_fdt64(re->size); re.size = cpu_to_fdt64(size);
return data_append_data(d, &bere, sizeof(bere)); return data_append_data(d, &re, sizeof(re));
} }
struct data data_append_cell(struct data d, cell_t word) struct data data_append_cell(struct data d, cell_t word)
......
...@@ -62,7 +62,8 @@ static int dts_version = 1; ...@@ -62,7 +62,8 @@ static int dts_version = 1;
static void push_input_file(const char *filename); static void push_input_file(const char *filename);
static bool pop_input_file(void); static bool pop_input_file(void);
static void lexical_error(const char *fmt, ...); static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
%} %}
%% %%
......
...@@ -655,8 +655,9 @@ static int dts_version = 1; ...@@ -655,8 +655,9 @@ static int dts_version = 1;
static void push_input_file(const char *filename); static void push_input_file(const char *filename);
static bool pop_input_file(void); static bool pop_input_file(void);
static void lexical_error(const char *fmt, ...); static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
#line 660 "dtc-lexer.lex.c"
#line 661 "dtc-lexer.lex.c"
#define INITIAL 0 #define INITIAL 0
#define BYTESTRING 1 #define BYTESTRING 1
...@@ -878,9 +879,9 @@ YY_DECL ...@@ -878,9 +879,9 @@ YY_DECL
} }
{ {
#line 68 "dtc-lexer.l" #line 69 "dtc-lexer.l"
#line 884 "dtc-lexer.lex.c" #line 885 "dtc-lexer.lex.c"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{ {
...@@ -937,7 +938,7 @@ do_action: /* This label is used only to access EOF actions. */ ...@@ -937,7 +938,7 @@ do_action: /* This label is used only to access EOF actions. */
case 1: case 1:
/* rule 1 can match eol */ /* rule 1 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 69 "dtc-lexer.l" #line 70 "dtc-lexer.l"
{ {
char *name = strchr(yytext, '\"') + 1; char *name = strchr(yytext, '\"') + 1;
yytext[yyleng-1] = '\0'; yytext[yyleng-1] = '\0';
...@@ -947,7 +948,7 @@ YY_RULE_SETUP ...@@ -947,7 +948,7 @@ YY_RULE_SETUP
case 2: case 2:
/* rule 2 can match eol */ /* rule 2 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 75 "dtc-lexer.l" #line 76 "dtc-lexer.l"
{ {
char *line, *fnstart, *fnend; char *line, *fnstart, *fnend;
struct data fn; struct data fn;
...@@ -981,7 +982,7 @@ case YY_STATE_EOF(INITIAL): ...@@ -981,7 +982,7 @@ case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(BYTESTRING): case YY_STATE_EOF(BYTESTRING):
case YY_STATE_EOF(PROPNODENAME): case YY_STATE_EOF(PROPNODENAME):
case YY_STATE_EOF(V1): case YY_STATE_EOF(V1):
#line 104 "dtc-lexer.l" #line 105 "dtc-lexer.l"
{ {
if (!pop_input_file()) { if (!pop_input_file()) {
yyterminate(); yyterminate();
...@@ -991,7 +992,7 @@ case YY_STATE_EOF(V1): ...@@ -991,7 +992,7 @@ case YY_STATE_EOF(V1):
case 3: case 3:
/* rule 3 can match eol */ /* rule 3 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 110 "dtc-lexer.l" #line 111 "dtc-lexer.l"
{ {
DPRINT("String: %s\n", yytext); DPRINT("String: %s\n", yytext);
yylval.data = data_copy_escape_string(yytext+1, yylval.data = data_copy_escape_string(yytext+1,
...@@ -1001,7 +1002,7 @@ YY_RULE_SETUP ...@@ -1001,7 +1002,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 4: case 4:
YY_RULE_SETUP YY_RULE_SETUP
#line 117 "dtc-lexer.l" #line 118 "dtc-lexer.l"
{ {
DPRINT("Keyword: /dts-v1/\n"); DPRINT("Keyword: /dts-v1/\n");
dts_version = 1; dts_version = 1;
...@@ -1011,7 +1012,7 @@ YY_RULE_SETUP ...@@ -1011,7 +1012,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 5: case 5:
YY_RULE_SETUP YY_RULE_SETUP
#line 124 "dtc-lexer.l" #line 125 "dtc-lexer.l"
{ {
DPRINT("Keyword: /plugin/\n"); DPRINT("Keyword: /plugin/\n");
return DT_PLUGIN; return DT_PLUGIN;
...@@ -1019,7 +1020,7 @@ YY_RULE_SETUP ...@@ -1019,7 +1020,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 6: case 6:
YY_RULE_SETUP YY_RULE_SETUP
#line 129 "dtc-lexer.l" #line 130 "dtc-lexer.l"
{ {
DPRINT("Keyword: /memreserve/\n"); DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT(); BEGIN_DEFAULT();
...@@ -1028,7 +1029,7 @@ YY_RULE_SETUP ...@@ -1028,7 +1029,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 7: case 7:
YY_RULE_SETUP YY_RULE_SETUP
#line 135 "dtc-lexer.l" #line 136 "dtc-lexer.l"
{ {
DPRINT("Keyword: /bits/\n"); DPRINT("Keyword: /bits/\n");
BEGIN_DEFAULT(); BEGIN_DEFAULT();
...@@ -1037,7 +1038,7 @@ YY_RULE_SETUP ...@@ -1037,7 +1038,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 8: case 8:
YY_RULE_SETUP YY_RULE_SETUP
#line 141 "dtc-lexer.l" #line 142 "dtc-lexer.l"
{ {
DPRINT("Keyword: /delete-property/\n"); DPRINT("Keyword: /delete-property/\n");
DPRINT("<PROPNODENAME>\n"); DPRINT("<PROPNODENAME>\n");
...@@ -1047,7 +1048,7 @@ YY_RULE_SETUP ...@@ -1047,7 +1048,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 9: case 9:
YY_RULE_SETUP YY_RULE_SETUP
#line 148 "dtc-lexer.l" #line 149 "dtc-lexer.l"
{ {
DPRINT("Keyword: /delete-node/\n"); DPRINT("Keyword: /delete-node/\n");
DPRINT("<PROPNODENAME>\n"); DPRINT("<PROPNODENAME>\n");
...@@ -1057,7 +1058,7 @@ YY_RULE_SETUP ...@@ -1057,7 +1058,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 10: case 10:
YY_RULE_SETUP YY_RULE_SETUP
#line 155 "dtc-lexer.l" #line 156 "dtc-lexer.l"
{ {
DPRINT("Label: %s\n", yytext); DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext); yylval.labelref = xstrdup(yytext);
...@@ -1067,7 +1068,7 @@ YY_RULE_SETUP ...@@ -1067,7 +1068,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 11: case 11:
YY_RULE_SETUP YY_RULE_SETUP
#line 162 "dtc-lexer.l" #line 163 "dtc-lexer.l"
{ {
char *e; char *e;
DPRINT("Integer Literal: '%s'\n", yytext); DPRINT("Integer Literal: '%s'\n", yytext);
...@@ -1093,7 +1094,7 @@ YY_RULE_SETUP ...@@ -1093,7 +1094,7 @@ YY_RULE_SETUP
case 12: case 12:
/* rule 12 can match eol */ /* rule 12 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 184 "dtc-lexer.l" #line 185 "dtc-lexer.l"
{ {
struct data d; struct data d;
DPRINT("Character literal: %s\n", yytext); DPRINT("Character literal: %s\n", yytext);
...@@ -1117,7 +1118,7 @@ YY_RULE_SETUP ...@@ -1117,7 +1118,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 13: case 13:
YY_RULE_SETUP YY_RULE_SETUP
#line 205 "dtc-lexer.l" #line 206 "dtc-lexer.l"
{ /* label reference */ { /* label reference */
DPRINT("Ref: %s\n", yytext+1); DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1); yylval.labelref = xstrdup(yytext+1);
...@@ -1126,7 +1127,7 @@ YY_RULE_SETUP ...@@ -1126,7 +1127,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 14: case 14:
YY_RULE_SETUP YY_RULE_SETUP
#line 211 "dtc-lexer.l" #line 212 "dtc-lexer.l"
{ /* new-style path reference */ { /* new-style path reference */
yytext[yyleng-1] = '\0'; yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2); DPRINT("Ref: %s\n", yytext+2);
...@@ -1136,7 +1137,7 @@ YY_RULE_SETUP ...@@ -1136,7 +1137,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 15: case 15:
YY_RULE_SETUP YY_RULE_SETUP
#line 218 "dtc-lexer.l" #line 219 "dtc-lexer.l"
{ {
yylval.byte = strtol(yytext, NULL, 16); yylval.byte = strtol(yytext, NULL, 16);
DPRINT("Byte: %02x\n", (int)yylval.byte); DPRINT("Byte: %02x\n", (int)yylval.byte);
...@@ -1145,7 +1146,7 @@ YY_RULE_SETUP ...@@ -1145,7 +1146,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 16: case 16:
YY_RULE_SETUP YY_RULE_SETUP
#line 224 "dtc-lexer.l" #line 225 "dtc-lexer.l"
{ {
DPRINT("/BYTESTRING\n"); DPRINT("/BYTESTRING\n");
BEGIN_DEFAULT(); BEGIN_DEFAULT();
...@@ -1154,7 +1155,7 @@ YY_RULE_SETUP ...@@ -1154,7 +1155,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 17: case 17:
YY_RULE_SETUP YY_RULE_SETUP
#line 230 "dtc-lexer.l" #line 231 "dtc-lexer.l"
{ {
DPRINT("PropNodeName: %s\n", yytext); DPRINT("PropNodeName: %s\n", yytext);
yylval.propnodename = xstrdup((yytext[0] == '\\') ? yylval.propnodename = xstrdup((yytext[0] == '\\') ?
...@@ -1165,7 +1166,7 @@ YY_RULE_SETUP ...@@ -1165,7 +1166,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 18: case 18:
YY_RULE_SETUP YY_RULE_SETUP
#line 238 "dtc-lexer.l" #line 239 "dtc-lexer.l"
{ {
DPRINT("Binary Include\n"); DPRINT("Binary Include\n");
return DT_INCBIN; return DT_INCBIN;
...@@ -1174,64 +1175,64 @@ YY_RULE_SETUP ...@@ -1174,64 +1175,64 @@ YY_RULE_SETUP
case 19: case 19:
/* rule 19 can match eol */ /* rule 19 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 243 "dtc-lexer.l" #line 244 "dtc-lexer.l"
/* eat whitespace */ /* eat whitespace */
YY_BREAK YY_BREAK
case 20: case 20:
/* rule 20 can match eol */ /* rule 20 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 244 "dtc-lexer.l" #line 245 "dtc-lexer.l"
/* eat C-style comments */ /* eat C-style comments */
YY_BREAK YY_BREAK
case 21: case 21:
/* rule 21 can match eol */ /* rule 21 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 245 "dtc-lexer.l" #line 246 "dtc-lexer.l"
/* eat C++-style comments */ /* eat C++-style comments */
YY_BREAK YY_BREAK
case 22: case 22:
YY_RULE_SETUP YY_RULE_SETUP
#line 247 "dtc-lexer.l" #line 248 "dtc-lexer.l"
{ return DT_LSHIFT; }; { return DT_LSHIFT; };
YY_BREAK YY_BREAK
case 23: case 23:
YY_RULE_SETUP YY_RULE_SETUP
#line 248 "dtc-lexer.l" #line 249 "dtc-lexer.l"
{ return DT_RSHIFT; }; { return DT_RSHIFT; };
YY_BREAK YY_BREAK
case 24: case 24:
YY_RULE_SETUP YY_RULE_SETUP
#line 249 "dtc-lexer.l" #line 250 "dtc-lexer.l"
{ return DT_LE; }; { return DT_LE; };
YY_BREAK YY_BREAK
case 25: case 25:
YY_RULE_SETUP YY_RULE_SETUP
#line 250 "dtc-lexer.l" #line 251 "dtc-lexer.l"
{ return DT_GE; }; { return DT_GE; };
YY_BREAK YY_BREAK
case 26: case 26:
YY_RULE_SETUP YY_RULE_SETUP
#line 251 "dtc-lexer.l" #line 252 "dtc-lexer.l"
{ return DT_EQ; }; { return DT_EQ; };
YY_BREAK YY_BREAK
case 27: case 27:
YY_RULE_SETUP YY_RULE_SETUP
#line 252 "dtc-lexer.l" #line 253 "dtc-lexer.l"
{ return DT_NE; }; { return DT_NE; };
YY_BREAK YY_BREAK
case 28: case 28:
YY_RULE_SETUP YY_RULE_SETUP
#line 253 "dtc-lexer.l" #line 254 "dtc-lexer.l"
{ return DT_AND; }; { return DT_AND; };
YY_BREAK YY_BREAK
case 29: case 29:
YY_RULE_SETUP YY_RULE_SETUP
#line 254 "dtc-lexer.l" #line 255 "dtc-lexer.l"
{ return DT_OR; }; { return DT_OR; };
YY_BREAK YY_BREAK
case 30: case 30:
YY_RULE_SETUP YY_RULE_SETUP
#line 256 "dtc-lexer.l" #line 257 "dtc-lexer.l"
{ {
DPRINT("Char: %c (\\x%02x)\n", yytext[0], DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]); (unsigned)yytext[0]);
...@@ -1249,10 +1250,10 @@ YY_RULE_SETUP ...@@ -1249,10 +1250,10 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 31: case 31:
YY_RULE_SETUP YY_RULE_SETUP
#line 271 "dtc-lexer.l" #line 272 "dtc-lexer.l"
ECHO; ECHO;
YY_BREAK YY_BREAK
#line 1256 "dtc-lexer.lex.c" #line 1257 "dtc-lexer.lex.c"
case YY_END_OF_BUFFER: case YY_END_OF_BUFFER:
{ {
...@@ -2218,7 +2219,7 @@ void yyfree (void * ptr ) ...@@ -2218,7 +2219,7 @@ void yyfree (void * ptr )
#define YYTABLES_NAME "yytables" #define YYTABLES_NAME "yytables"
#line 271 "dtc-lexer.l" #line 272 "dtc-lexer.l"
......
...@@ -1557,10 +1557,10 @@ yyreduce: ...@@ -1557,10 +1557,10 @@ yyreduce:
{ {
struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref)); struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref));
add_label(&target->labels, (yyvsp[-2].labelref)); if (target) {
if (target) add_label(&target->labels, (yyvsp[-2].labelref));
merge_nodes(target, (yyvsp[0].node)); merge_nodes(target, (yyvsp[0].node));
else } else
ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref)); ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref));
(yyval.node) = (yyvsp[-3].node); (yyval.node) = (yyvsp[-3].node);
} }
......
...@@ -171,10 +171,10 @@ devicetree: ...@@ -171,10 +171,10 @@ devicetree:
{ {
struct node *target = get_node_by_ref($1, $3); struct node *target = get_node_by_ref($1, $3);
add_label(&target->labels, $2); if (target) {
if (target) add_label(&target->labels, $2);
merge_nodes(target, $4); merge_nodes(target, $4);
else } else
ERROR(&@3, "Label or path %s not found", $3); ERROR(&@3, "Label or path %s not found", $3);
$$ = $1; $$ = $1;
} }
......
...@@ -138,7 +138,7 @@ static const char *guess_type_by_name(const char *fname, const char *fallback) ...@@ -138,7 +138,7 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
static const char *guess_input_format(const char *fname, const char *fallback) static const char *guess_input_format(const char *fname, const char *fallback)
{ {
struct stat statbuf; struct stat statbuf;
uint32_t magic; fdt32_t magic;
FILE *f; FILE *f;
if (stat(fname, &statbuf) != 0) if (stat(fname, &statbuf) != 0)
...@@ -159,8 +159,7 @@ static const char *guess_input_format(const char *fname, const char *fallback) ...@@ -159,8 +159,7 @@ static const char *guess_input_format(const char *fname, const char *fallback)
} }
fclose(f); fclose(f);
magic = fdt32_to_cpu(magic); if (fdt32_to_cpu(magic) == FDT_MAGIC)
if (magic == FDT_MAGIC)
return "dtb"; return "dtb";
return guess_type_by_name(fname, fallback); return guess_type_by_name(fname, fallback);
...@@ -216,7 +215,7 @@ int main(int argc, char *argv[]) ...@@ -216,7 +215,7 @@ int main(int argc, char *argv[])
alignsize = strtol(optarg, NULL, 0); alignsize = strtol(optarg, NULL, 0);
if (!is_power_of_2(alignsize)) if (!is_power_of_2(alignsize))
die("Invalid argument \"%d\" to -a option\n", die("Invalid argument \"%d\" to -a option\n",
optarg); alignsize);
break; break;
case 'f': case 'f':
force = true; force = true;
...@@ -309,6 +308,8 @@ int main(int argc, char *argv[]) ...@@ -309,6 +308,8 @@ int main(int argc, char *argv[])
else else
die("Unknown input format \"%s\"\n", inform); die("Unknown input format \"%s\"\n", inform);
dti->outname = outname;
if (depfile) { if (depfile) {
fputc('\n', depfile); fputc('\n', depfile);
fclose(depfile); fclose(depfile);
......
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
#define debug(...) #define debug(...)
#endif #endif
#define DEFAULT_FDT_VERSION 17 #define DEFAULT_FDT_VERSION 17
/* /*
...@@ -114,7 +113,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m, ...@@ -114,7 +113,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m,
struct data data_merge(struct data d1, struct data d2); struct data data_merge(struct data d1, struct data d2);
struct data data_append_cell(struct data d, cell_t word); struct data data_append_cell(struct data d, cell_t word);
struct data data_append_integer(struct data d, uint64_t word, int bits); struct data data_append_integer(struct data d, uint64_t word, int bits);
struct data data_append_re(struct data d, const struct fdt_reserve_entry *re); struct data data_append_re(struct data d, uint64_t address, uint64_t size);
struct data data_append_addr(struct data d, uint64_t addr); struct data data_append_addr(struct data d, uint64_t addr);
struct data data_append_byte(struct data d, uint8_t byte); struct data data_append_byte(struct data d, uint8_t byte);
struct data data_append_zeroes(struct data d, int len); struct data data_append_zeroes(struct data d, int len);
...@@ -136,6 +135,10 @@ struct label { ...@@ -136,6 +135,10 @@ struct label {
struct label *next; struct label *next;
}; };
struct bus_type {
const char *name;
};
struct property { struct property {
bool deleted; bool deleted;
char *name; char *name;
...@@ -162,6 +165,7 @@ struct node { ...@@ -162,6 +165,7 @@ struct node {
int addr_cells, size_cells; int addr_cells, size_cells;
struct label *labels; struct label *labels;
const struct bus_type *bus;
}; };
#define for_each_label_withdel(l0, l) \ #define for_each_label_withdel(l0, l) \
...@@ -227,7 +231,7 @@ uint32_t guess_boot_cpuid(struct node *tree); ...@@ -227,7 +231,7 @@ uint32_t guess_boot_cpuid(struct node *tree);
/* Boot info (tree plus memreserve information */ /* Boot info (tree plus memreserve information */
struct reserve_info { struct reserve_info {
struct fdt_reserve_entry re; uint64_t address, size;
struct reserve_info *next; struct reserve_info *next;
...@@ -246,6 +250,7 @@ struct dt_info { ...@@ -246,6 +250,7 @@ struct dt_info {
struct reserve_info *reservelist; struct reserve_info *reservelist;
uint32_t boot_cpuid_phys; uint32_t boot_cpuid_phys;
struct node *dt; /* the device tree */ struct node *dt; /* the device tree */
const char *outname; /* filename being written to, "-" for stdout */
}; };
/* DTS version flags definitions */ /* DTS version flags definitions */
......
...@@ -49,7 +49,7 @@ static struct version_info { ...@@ -49,7 +49,7 @@ static struct version_info {
struct emitter { struct emitter {
void (*cell)(void *, cell_t); void (*cell)(void *, cell_t);
void (*string)(void *, char *, int); void (*string)(void *, const char *, int);
void (*align)(void *, int); void (*align)(void *, int);
void (*data)(void *, struct data); void (*data)(void *, struct data);
void (*beginnode)(void *, struct label *labels); void (*beginnode)(void *, struct label *labels);
...@@ -64,7 +64,7 @@ static void bin_emit_cell(void *e, cell_t val) ...@@ -64,7 +64,7 @@ static void bin_emit_cell(void *e, cell_t val)
*dtbuf = data_append_cell(*dtbuf, val); *dtbuf = data_append_cell(*dtbuf, val);
} }
static void bin_emit_string(void *e, char *str, int len) static void bin_emit_string(void *e, const char *str, int len)
{ {
struct data *dtbuf = e; struct data *dtbuf = e;
...@@ -144,22 +144,14 @@ static void asm_emit_cell(void *e, cell_t val) ...@@ -144,22 +144,14 @@ static void asm_emit_cell(void *e, cell_t val)
(val >> 8) & 0xff, val & 0xff); (val >> 8) & 0xff, val & 0xff);
} }
static void asm_emit_string(void *e, char *str, int len) static void asm_emit_string(void *e, const char *str, int len)
{ {
FILE *f = e; FILE *f = e;
char c = 0;
if (len != 0) { if (len != 0)
/* XXX: ewww */ fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
c = str[len]; else
str[len] = '\0'; fprintf(f, "\t.string\t\"%s\"\n", str);
}
fprintf(f, "\t.string\t\"%s\"\n", str);
if (len != 0) {
str[len] = c;
}
} }
static void asm_emit_align(void *e, int a) static void asm_emit_align(void *e, int a)
...@@ -179,7 +171,7 @@ static void asm_emit_data(void *e, struct data d) ...@@ -179,7 +171,7 @@ static void asm_emit_data(void *e, struct data d)
emit_offset_label(f, m->ref, m->offset); emit_offset_label(f, m->ref, m->offset);
while ((d.len - off) >= sizeof(uint32_t)) { while ((d.len - off) >= sizeof(uint32_t)) {
asm_emit_cell(e, fdt32_to_cpu(*((uint32_t *)(d.val+off)))); asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off))));
off += sizeof(uint32_t); off += sizeof(uint32_t);
} }
...@@ -318,17 +310,16 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist, ...@@ -318,17 +310,16 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
{ {
struct reserve_info *re; struct reserve_info *re;
struct data d = empty_data; struct data d = empty_data;
static struct fdt_reserve_entry null_re = {0,0};
int j; int j;
for (re = reservelist; re; re = re->next) { for (re = reservelist; re; re = re->next) {
d = data_append_re(d, &re->re); d = data_append_re(d, re->address, re->size);
} }
/* /*
* Add additional reserved slots if the user asked for them. * Add additional reserved slots if the user asked for them.
*/ */
for (j = 0; j < reservenum; j++) { for (j = 0; j < reservenum; j++) {
d = data_append_re(d, &null_re); d = data_append_re(d, 0, 0);
} }
return d; return d;
...@@ -544,11 +535,11 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version) ...@@ -544,11 +535,11 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)
fprintf(f, "\t.globl\t%s\n", l->label); fprintf(f, "\t.globl\t%s\n", l->label);
fprintf(f, "%s:\n", l->label); fprintf(f, "%s:\n", l->label);
} }
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32)); ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->address >> 32));
ASM_EMIT_BELONG(f, "0x%08x", ASM_EMIT_BELONG(f, "0x%08x",
(unsigned int)(re->re.address & 0xffffffff)); (unsigned int)(re->address & 0xffffffff));
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32)); ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32));
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff)); ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff));
} }
for (i = 0; i < reservenum; i++) { for (i = 0; i < reservenum; i++) {
fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
...@@ -609,7 +600,7 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len) ...@@ -609,7 +600,7 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len)
static uint32_t flat_read_word(struct inbuf *inb) static uint32_t flat_read_word(struct inbuf *inb)
{ {
uint32_t val; fdt32_t val;
assert(((inb->ptr - inb->base) % sizeof(val)) == 0); assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
...@@ -718,13 +709,15 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) ...@@ -718,13 +709,15 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
* First pass, count entries. * First pass, count entries.
*/ */
while (1) { while (1) {
uint64_t address, size;
flat_read_chunk(inb, &re, sizeof(re)); flat_read_chunk(inb, &re, sizeof(re));
re.address = fdt64_to_cpu(re.address); address = fdt64_to_cpu(re.address);
re.size = fdt64_to_cpu(re.size); size = fdt64_to_cpu(re.size);
if (re.size == 0) if (size == 0)
break; break;
new = build_reserve_entry(re.address, re.size); new = build_reserve_entry(address, size);
reservelist = add_reserve_entry(reservelist, new); reservelist = add_reserve_entry(reservelist, new);
} }
...@@ -817,6 +810,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, ...@@ -817,6 +810,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
struct dt_info *dt_from_blob(const char *fname) struct dt_info *dt_from_blob(const char *fname)
{ {
FILE *f; FILE *f;
fdt32_t magic_buf, totalsize_buf;
uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys; uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
uint32_t off_dt, off_str, off_mem_rsvmap; uint32_t off_dt, off_str, off_mem_rsvmap;
int rc; int rc;
...@@ -833,7 +827,7 @@ struct dt_info *dt_from_blob(const char *fname) ...@@ -833,7 +827,7 @@ struct dt_info *dt_from_blob(const char *fname)
f = srcfile_relative_open(fname, NULL); f = srcfile_relative_open(fname, NULL);
rc = fread(&magic, sizeof(magic), 1, f); rc = fread(&magic_buf, sizeof(magic_buf), 1, f);
if (ferror(f)) if (ferror(f))
die("Error reading DT blob magic number: %s\n", die("Error reading DT blob magic number: %s\n",
strerror(errno)); strerror(errno));
...@@ -844,11 +838,11 @@ struct dt_info *dt_from_blob(const char *fname) ...@@ -844,11 +838,11 @@ struct dt_info *dt_from_blob(const char *fname)
die("Mysterious short read reading magic number\n"); die("Mysterious short read reading magic number\n");
} }
magic = fdt32_to_cpu(magic); magic = fdt32_to_cpu(magic_buf);
if (magic != FDT_MAGIC) if (magic != FDT_MAGIC)
die("Blob has incorrect magic number\n"); die("Blob has incorrect magic number\n");
rc = fread(&totalsize, sizeof(totalsize), 1, f); rc = fread(&totalsize_buf, sizeof(totalsize_buf), 1, f);
if (ferror(f)) if (ferror(f))
die("Error reading DT blob size: %s\n", strerror(errno)); die("Error reading DT blob size: %s\n", strerror(errno));
if (rc < 1) { if (rc < 1) {
...@@ -858,7 +852,7 @@ struct dt_info *dt_from_blob(const char *fname) ...@@ -858,7 +852,7 @@ struct dt_info *dt_from_blob(const char *fname)
die("Mysterious short read reading blob size\n"); die("Mysterious short read reading blob size\n");
} }
totalsize = fdt32_to_cpu(totalsize); totalsize = fdt32_to_cpu(totalsize_buf);
if (totalsize < FDT_V1_SIZE) if (totalsize < FDT_V1_SIZE)
die("DT blob size (%d) is too small\n", totalsize); die("DT blob size (%d) is too small\n", totalsize);
......
...@@ -283,7 +283,8 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, ...@@ -283,7 +283,8 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
if (err) if (err)
return err; return err;
memcpy(prop->data, val, len); if (len)
memcpy(prop->data, val, len);
return 0; return 0;
} }
......
...@@ -143,7 +143,9 @@ ...@@ -143,7 +143,9 @@
/* Low-level functions (you probably don't need these) */ /* Low-level functions (you probably don't need these) */
/**********************************************************************/ /**********************************************************************/
#ifndef SWIG /* This function is not useful in Python */
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
#endif
static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
{ {
return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
...@@ -210,7 +212,6 @@ int fdt_next_subnode(const void *fdt, int offset); ...@@ -210,7 +212,6 @@ int fdt_next_subnode(const void *fdt, int offset);
/**********************************************************************/ /**********************************************************************/
/* General functions */ /* General functions */
/**********************************************************************/ /**********************************************************************/
#define fdt_get_header(fdt, field) \ #define fdt_get_header(fdt, field) \
(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) #define fdt_magic(fdt) (fdt_get_header(fdt, magic))
...@@ -354,8 +355,10 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); ...@@ -354,8 +355,10 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
* useful for finding subnodes based on a portion of a larger string, * useful for finding subnodes based on a portion of a larger string,
* such as a full path. * such as a full path.
*/ */
#ifndef SWIG /* Not available in Python */
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
const char *name, int namelen); const char *name, int namelen);
#endif
/** /**
* fdt_subnode_offset - find a subnode of a given node * fdt_subnode_offset - find a subnode of a given node
* @fdt: pointer to the device tree blob * @fdt: pointer to the device tree blob
...@@ -391,7 +394,9 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); ...@@ -391,7 +394,9 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
* Identical to fdt_path_offset(), but only consider the first namelen * Identical to fdt_path_offset(), but only consider the first namelen
* characters of path as the path name. * characters of path as the path name.
*/ */
#ifndef SWIG /* Not available in Python */
int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
#endif
/** /**
* fdt_path_offset - find a tree node by its full path * fdt_path_offset - find a tree node by its full path
...@@ -550,10 +555,12 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, ...@@ -550,10 +555,12 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
* Identical to fdt_get_property(), but only examine the first namelen * Identical to fdt_get_property(), but only examine the first namelen
* characters of name for matching the property name. * characters of name for matching the property name.
*/ */
#ifndef SWIG /* Not available in Python */
const struct fdt_property *fdt_get_property_namelen(const void *fdt, const struct fdt_property *fdt_get_property_namelen(const void *fdt,
int nodeoffset, int nodeoffset,
const char *name, const char *name,
int namelen, int *lenp); int namelen, int *lenp);
#endif
/** /**
* fdt_get_property - find a given property in a given node * fdt_get_property - find a given property in a given node
...@@ -624,8 +631,10 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, ...@@ -624,8 +631,10 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
* -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_TRUNCATED, standard meanings * -FDT_ERR_TRUNCATED, standard meanings
*/ */
#ifndef SWIG /* This function is not useful in Python */
const void *fdt_getprop_by_offset(const void *fdt, int offset, const void *fdt_getprop_by_offset(const void *fdt, int offset,
const char **namep, int *lenp); const char **namep, int *lenp);
#endif
/** /**
* fdt_getprop_namelen - get property value based on substring * fdt_getprop_namelen - get property value based on substring
...@@ -638,6 +647,7 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, ...@@ -638,6 +647,7 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
* Identical to fdt_getprop(), but only examine the first namelen * Identical to fdt_getprop(), but only examine the first namelen
* characters of name for matching the property name. * characters of name for matching the property name.
*/ */
#ifndef SWIG /* Not available in Python */
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
const char *name, int namelen, int *lenp); const char *name, int namelen, int *lenp);
static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
...@@ -647,6 +657,7 @@ static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, ...@@ -647,6 +657,7 @@ static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name, return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
namelen, lenp); namelen, lenp);
} }
#endif
/** /**
* fdt_getprop - retrieve the value of a given property * fdt_getprop - retrieve the value of a given property
...@@ -707,8 +718,10 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); ...@@ -707,8 +718,10 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
* Identical to fdt_get_alias(), but only examine the first namelen * Identical to fdt_get_alias(), but only examine the first namelen
* characters of name for matching the alias name. * characters of name for matching the alias name.
*/ */
#ifndef SWIG /* Not available in Python */
const char *fdt_get_alias_namelen(const void *fdt, const char *fdt_get_alias_namelen(const void *fdt,
const char *name, int namelen); const char *name, int namelen);
#endif
/** /**
* fdt_get_alias - retrieve the path referenced by a given alias * fdt_get_alias - retrieve the path referenced by a given alias
...@@ -1106,10 +1119,12 @@ int fdt_size_cells(const void *fdt, int nodeoffset); ...@@ -1106,10 +1119,12 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
* of the name. It is useful when you want to manipulate only one value of * of the name. It is useful when you want to manipulate only one value of
* an array and you have a string that doesn't end with \0. * an array and you have a string that doesn't end with \0.
*/ */
#ifndef SWIG /* Not available in Python */
int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
const char *name, int namelen, const char *name, int namelen,
uint32_t idx, const void *val, uint32_t idx, const void *val,
int len); int len);
#endif
/** /**
* fdt_setprop_inplace - change a property's value, but not its size * fdt_setprop_inplace - change a property's value, but not its size
...@@ -1139,8 +1154,10 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, ...@@ -1139,8 +1154,10 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
* -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_TRUNCATED, standard meanings * -FDT_ERR_TRUNCATED, standard meanings
*/ */
#ifndef SWIG /* Not available in Python */
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
const void *val, int len); const void *val, int len);
#endif
/** /**
* fdt_setprop_inplace_u32 - change the value of a 32-bit integer property * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
...@@ -1527,6 +1544,36 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, ...@@ -1527,6 +1544,36 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
#define fdt_setprop_string(fdt, nodeoffset, name, str) \ #define fdt_setprop_string(fdt, nodeoffset, name, str) \
fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
/**
* fdt_setprop_empty - set a property to an empty value
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
*
* fdt_setprop_empty() sets the value of the named property in the
* given node to an empty (zero length) value, or creates a new empty
* property if it does not already exist.
*
* This function may insert or delete data from the blob, and will
* therefore change the offsets of some existing nodes.
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
* contain the new property value
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
#define fdt_setprop_empty(fdt, nodeoffset, name) \
fdt_setprop((fdt), (nodeoffset), (name), NULL, 0)
/** /**
* fdt_appendprop - append to or create a property * fdt_appendprop - append to or create a property
* @fdt: pointer to the device tree blob * @fdt: pointer to the device tree blob
...@@ -1704,8 +1751,10 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name); ...@@ -1704,8 +1751,10 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
* creating subnodes based on a portion of a larger string, such as a * creating subnodes based on a portion of a larger string, such as a
* full path. * full path.
*/ */
#ifndef SWIG /* Not available in Python */
int fdt_add_subnode_namelen(void *fdt, int parentoffset, int fdt_add_subnode_namelen(void *fdt, int parentoffset,
const char *name, int namelen); const char *name, int namelen);
#endif
/** /**
* fdt_add_subnode - creates a new node * fdt_add_subnode - creates a new node
......
...@@ -58,16 +58,16 @@ ...@@ -58,16 +58,16 @@
#include <string.h> #include <string.h>
#ifdef __CHECKER__ #ifdef __CHECKER__
#define __force __attribute__((force)) #define FDT_FORCE __attribute__((force))
#define __bitwise __attribute__((bitwise)) #define FDT_BITWISE __attribute__((bitwise))
#else #else
#define __force #define FDT_FORCE
#define __bitwise #define FDT_BITWISE
#endif #endif
typedef uint16_t __bitwise fdt16_t; typedef uint16_t FDT_BITWISE fdt16_t;
typedef uint32_t __bitwise fdt32_t; typedef uint32_t FDT_BITWISE fdt32_t;
typedef uint64_t __bitwise fdt64_t; typedef uint64_t FDT_BITWISE fdt64_t;
#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n]) #define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n])
#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) #define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1))
...@@ -80,29 +80,29 @@ typedef uint64_t __bitwise fdt64_t; ...@@ -80,29 +80,29 @@ typedef uint64_t __bitwise fdt64_t;
static inline uint16_t fdt16_to_cpu(fdt16_t x) static inline uint16_t fdt16_to_cpu(fdt16_t x)
{ {
return (__force uint16_t)CPU_TO_FDT16(x); return (FDT_FORCE uint16_t)CPU_TO_FDT16(x);
} }
static inline fdt16_t cpu_to_fdt16(uint16_t x) static inline fdt16_t cpu_to_fdt16(uint16_t x)
{ {
return (__force fdt16_t)CPU_TO_FDT16(x); return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x);
} }
static inline uint32_t fdt32_to_cpu(fdt32_t x) static inline uint32_t fdt32_to_cpu(fdt32_t x)
{ {
return (__force uint32_t)CPU_TO_FDT32(x); return (FDT_FORCE uint32_t)CPU_TO_FDT32(x);
} }
static inline fdt32_t cpu_to_fdt32(uint32_t x) static inline fdt32_t cpu_to_fdt32(uint32_t x)
{ {
return (__force fdt32_t)CPU_TO_FDT32(x); return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x);
} }
static inline uint64_t fdt64_to_cpu(fdt64_t x) static inline uint64_t fdt64_to_cpu(fdt64_t x)
{ {
return (__force uint64_t)CPU_TO_FDT64(x); return (FDT_FORCE uint64_t)CPU_TO_FDT64(x);
} }
static inline fdt64_t cpu_to_fdt64(uint64_t x) static inline fdt64_t cpu_to_fdt64(uint64_t x)
{ {
return (__force fdt64_t)CPU_TO_FDT64(x); return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x);
} }
#undef CPU_TO_FDT64 #undef CPU_TO_FDT64
#undef CPU_TO_FDT32 #undef CPU_TO_FDT32
......
...@@ -242,7 +242,7 @@ void delete_property_by_name(struct node *node, char *name) ...@@ -242,7 +242,7 @@ void delete_property_by_name(struct node *node, char *name)
struct property *prop = node->proplist; struct property *prop = node->proplist;
while (prop) { while (prop) {
if (!strcmp(prop->name, name)) { if (streq(prop->name, name)) {
delete_property(prop); delete_property(prop);
return; return;
} }
...@@ -275,7 +275,7 @@ void delete_node_by_name(struct node *parent, char *name) ...@@ -275,7 +275,7 @@ void delete_node_by_name(struct node *parent, char *name)
struct node *node = parent->children; struct node *node = parent->children;
while (node) { while (node) {
if (!strcmp(node->name, name)) { if (streq(node->name, name)) {
delete_node(node); delete_node(node);
return; return;
} }
...@@ -319,8 +319,8 @@ struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) ...@@ -319,8 +319,8 @@ struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
memset(new, 0, sizeof(*new)); memset(new, 0, sizeof(*new));
new->re.address = address; new->address = address;
new->re.size = size; new->size = size;
return new; return new;
} }
...@@ -393,7 +393,7 @@ struct property *get_property(struct node *node, const char *propname) ...@@ -393,7 +393,7 @@ struct property *get_property(struct node *node, const char *propname)
cell_t propval_cell(struct property *prop) cell_t propval_cell(struct property *prop)
{ {
assert(prop->val.len == sizeof(cell_t)); assert(prop->val.len == sizeof(cell_t));
return fdt32_to_cpu(*((cell_t *)prop->val.val)); return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
} }
struct property *get_property_by_label(struct node *tree, const char *label, struct property *get_property_by_label(struct node *tree, const char *label,
...@@ -599,13 +599,13 @@ static int cmp_reserve_info(const void *ax, const void *bx) ...@@ -599,13 +599,13 @@ static int cmp_reserve_info(const void *ax, const void *bx)
a = *((const struct reserve_info * const *)ax); a = *((const struct reserve_info * const *)ax);
b = *((const struct reserve_info * const *)bx); b = *((const struct reserve_info * const *)bx);
if (a->re.address < b->re.address) if (a->address < b->address)
return -1; return -1;
else if (a->re.address > b->re.address) else if (a->address > b->address)
return 1; return 1;
else if (a->re.size < b->re.size) else if (a->size < b->size)
return -1; return -1;
else if (a->re.size > b->re.size) else if (a->size > b->size)
return 1; return 1;
else else
return 0; return 0;
...@@ -847,6 +847,8 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn, ...@@ -847,6 +847,8 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn,
xasprintf(&entry, "%s:%s:%u", xasprintf(&entry, "%s:%s:%u",
node->fullpath, prop->name, m->offset); node->fullpath, prop->name, m->offset);
append_to_property(fn, m->ref, entry, strlen(entry) + 1); append_to_property(fn, m->ref, entry, strlen(entry) + 1);
free(entry);
} }
static void generate_fixups_tree_internal(struct dt_info *dti, static void generate_fixups_tree_internal(struct dt_info *dti,
...@@ -900,7 +902,7 @@ static void add_local_fixup_entry(struct dt_info *dti, ...@@ -900,7 +902,7 @@ static void add_local_fixup_entry(struct dt_info *dti,
struct node *refnode) struct node *refnode)
{ {
struct node *wn, *nwn; /* local fixup node, walk node, new */ struct node *wn, *nwn; /* local fixup node, walk node, new */
uint32_t value_32; fdt32_t value_32;
char **compp; char **compp;
int i, depth; int i, depth;
......
...@@ -252,7 +252,7 @@ srcpos_string(struct srcpos *pos) ...@@ -252,7 +252,7 @@ srcpos_string(struct srcpos *pos)
const char *fname = "<no-file>"; const char *fname = "<no-file>";
char *pos_str; char *pos_str;
if (pos) if (pos->file && pos->file->name)
fname = pos->file->name; fname = pos->file->name;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include "util.h"
struct srcfile_state { struct srcfile_state {
FILE *f; FILE *f;
...@@ -106,12 +107,10 @@ extern void srcpos_update(struct srcpos *pos, const char *text, int len); ...@@ -106,12 +107,10 @@ extern void srcpos_update(struct srcpos *pos, const char *text, int len);
extern struct srcpos *srcpos_copy(struct srcpos *pos); extern struct srcpos *srcpos_copy(struct srcpos *pos);
extern char *srcpos_string(struct srcpos *pos); extern char *srcpos_string(struct srcpos *pos);
extern void srcpos_verror(struct srcpos *pos, const char *prefix, extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix,
const char *fmt, va_list va) const char *fmt, va_list va);
__attribute__((format(printf, 3, 0))); extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix,
extern void srcpos_error(struct srcpos *pos, const char *prefix, const char *fmt, ...);
const char *fmt, ...)
__attribute__((format(printf, 3, 4)));
extern void srcpos_set_line(char *f, int l); extern void srcpos_set_line(char *f, int l);
......
...@@ -137,7 +137,7 @@ static void write_propval_string(FILE *f, struct data val) ...@@ -137,7 +137,7 @@ static void write_propval_string(FILE *f, struct data val)
static void write_propval_cells(FILE *f, struct data val) static void write_propval_cells(FILE *f, struct data val)
{ {
void *propend = val.val + val.len; void *propend = val.val + val.len;
cell_t *cp = (cell_t *)val.val; fdt32_t *cp = (fdt32_t *)val.val;
struct marker *m = val.markers; struct marker *m = val.markers;
fprintf(f, "<"); fprintf(f, "<");
...@@ -275,8 +275,8 @@ void dt_to_source(FILE *f, struct dt_info *dti) ...@@ -275,8 +275,8 @@ void dt_to_source(FILE *f, struct dt_info *dti)
for_each_label(re->labels, l) for_each_label(re->labels, l)
fprintf(f, "%s: ", l->label); fprintf(f, "%s: ", l->label);
fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
(unsigned long long)re->re.address, (unsigned long long)re->address,
(unsigned long long)re->re.size); (unsigned long long)re->size);
} }
write_tree_source_node(f, dti->dt, 0); write_tree_source_node(f, dti->dt, 0);
......
...@@ -36,10 +36,19 @@ DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c ...@@ -36,10 +36,19 @@ DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c
DTC_GENERATED="dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h" DTC_GENERATED="dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h"
LIBFDT_SOURCE="Makefile.libfdt fdt.c fdt.h fdt_empty_tree.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c fdt_wip.c libfdt.h libfdt_env.h libfdt_internal.h" LIBFDT_SOURCE="Makefile.libfdt fdt.c fdt.h fdt_empty_tree.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c fdt_wip.c libfdt.h libfdt_env.h libfdt_internal.h"
get_last_dtc_version() {
git log --oneline scripts/dtc/ | grep 'upstream' | head -1 | sed -e 's/^.* \(.*\)/\1/'
}
last_dtc_ver=$(get_last_dtc_version)
# Build DTC # Build DTC
cd $DTC_UPSTREAM_PATH cd $DTC_UPSTREAM_PATH
make clean make clean
make check make check
dtc_version=$(git describe HEAD)
dtc_log=$(git log --oneline ${last_dtc_ver}..)
# Copy the files into the Linux tree # Copy the files into the Linux tree
cd $DTC_LINUX_PATH cd $DTC_LINUX_PATH
...@@ -60,4 +69,13 @@ sed -i -- 's/#include <libfdt_env.h>/#include "libfdt_env.h"/g' ./libfdt/libfdt. ...@@ -60,4 +69,13 @@ sed -i -- 's/#include <libfdt_env.h>/#include "libfdt_env.h"/g' ./libfdt/libfdt.
sed -i -- 's/#include <fdt.h>/#include "fdt.h"/g' ./libfdt/libfdt.h sed -i -- 's/#include <fdt.h>/#include "fdt.h"/g' ./libfdt/libfdt.h
git add ./libfdt/libfdt.h git add ./libfdt/libfdt.h
git commit -e -v -m "scripts/dtc: Update to upstream version [CHANGEME]" commit_msg=$(cat << EOF
scripts/dtc: Update to upstream version ${dtc_version}
This adds the following commits from upstream:
${dtc_log}
EOF
)
git commit -e -v -s -m "${commit_msg}"
...@@ -396,7 +396,7 @@ void utilfdt_print_data(const char *data, int len) ...@@ -396,7 +396,7 @@ void utilfdt_print_data(const char *data, int len)
} while (s < data + len); } while (s < data + len);
} else if ((len % 4) == 0) { } else if ((len % 4) == 0) {
const uint32_t *cell = (const uint32_t *)data; const fdt32_t *cell = (const fdt32_t *)data;
printf(" = <"); printf(" = <");
for (i = 0, len /= 4; i < len; i++) for (i = 0, len /= 4; i < len; i++)
...@@ -412,15 +412,16 @@ void utilfdt_print_data(const char *data, int len) ...@@ -412,15 +412,16 @@ void utilfdt_print_data(const char *data, int len)
} }
} }
void util_version(void) void NORETURN util_version(void)
{ {
printf("Version: %s\n", DTC_VERSION); printf("Version: %s\n", DTC_VERSION);
exit(0); exit(0);
} }
void util_usage(const char *errmsg, const char *synopsis, void NORETURN util_usage(const char *errmsg, const char *synopsis,
const char *short_opts, struct option const long_opts[], const char *short_opts,
const char * const opts_help[]) struct option const long_opts[],
const char * const opts_help[])
{ {
FILE *fp = errmsg ? stderr : stdout; FILE *fp = errmsg ? stderr : stdout;
const char a_arg[] = "<arg>"; const char a_arg[] = "<arg>";
......
...@@ -25,9 +25,17 @@ ...@@ -25,9 +25,17 @@
* USA * USA
*/ */
#ifdef __GNUC__
#define PRINTF(i, j) __attribute__((format (printf, i, j)))
#define NORETURN __attribute__((noreturn))
#else
#define PRINTF(i, j)
#define NORETURN
#endif
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
static inline void __attribute__((noreturn)) die(const char *str, ...) static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
{ {
va_list ap; va_list ap;
...@@ -53,13 +61,14 @@ static inline void *xrealloc(void *p, size_t len) ...@@ -53,13 +61,14 @@ static inline void *xrealloc(void *p, size_t len)
void *new = realloc(p, len); void *new = realloc(p, len);
if (!new) if (!new)
die("realloc() failed (len=%d)\n", len); die("realloc() failed (len=%zd)\n", len);
return new; return new;
} }
extern char *xstrdup(const char *s); extern char *xstrdup(const char *s);
extern int xasprintf(char **strp, const char *fmt, ...);
extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
extern char *join_path(const char *path, const char *name); extern char *join_path(const char *path, const char *name);
/** /**
...@@ -188,7 +197,7 @@ void utilfdt_print_data(const char *data, int len); ...@@ -188,7 +197,7 @@ void utilfdt_print_data(const char *data, int len);
/** /**
* Show source version and exit * Show source version and exit
*/ */
void util_version(void) __attribute__((noreturn)); void NORETURN util_version(void);
/** /**
* Show usage and exit * Show usage and exit
...@@ -202,9 +211,10 @@ void util_version(void) __attribute__((noreturn)); ...@@ -202,9 +211,10 @@ void util_version(void) __attribute__((noreturn));
* @param long_opts The structure of long options * @param long_opts The structure of long options
* @param opts_help An array of help strings (should align with long_opts) * @param opts_help An array of help strings (should align with long_opts)
*/ */
void util_usage(const char *errmsg, const char *synopsis, void NORETURN util_usage(const char *errmsg, const char *synopsis,
const char *short_opts, struct option const long_opts[], const char *short_opts,
const char * const opts_help[]) __attribute__((noreturn)); struct option const long_opts[],
const char * const opts_help[]);
/** /**
* Show usage and exit * Show usage and exit
......
#define DTC_VERSION "DTC 1.4.2-g0931cea3" #define DTC_VERSION "DTC 1.4.4-g756ffc4f"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment