mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 22:24:11 +08:00
DeviceTree for 4.12:
- 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. -----BEGIN PGP SIGNATURE----- iQItBAABCAAXBQJZDM+bEBxyb2JoQGtlcm5lbC5vcmcACgkQ+vtdtY28YcM7Yw/+ NPgcfP2iFXWTC/D54neh/QliH7n5jO1YILQOd5ZJulTaKVCv1sNf4JCFVDQO/vuO 592f2jq/blhhh8yKrH0uzHvTADYO7G+XEv3D64Lu/MpmnBHTjut9WeG5h8SZWJD+ jGoz3Kx+Cmgxh/w1Ud/fh2qO3T0Es74TH+Ovi/AfpiywiYD8AqMlw0Tk+UtMRb12 NsihgiYXo8nT/BKe9aOFxOJjV9Pp+pSmyX5Mu2IdOtLnl0MXk5Rvn0mXLU2/oN5n MONTyielvLB9opxaaSeSBadv3iXcVTagH6MinYjeQRwsLGWDy2YzxLccC/jBkyR5 v8X/IJtpivUzCm3ji+mFEKje5u5c+N3ZLhKmTkeyNBJGwrnD7zj0gVcM5GGdK5aW Q4exqECklSgmpiCvlL1KWyXi3QsgMuu/wbsv5H5PgDe1wgMAtfKPrIm4kPpbLpW2 Dp+scFfL1v9drfvbcEum6PNw2/EGZY/okaRlcr0zFn8eMsa+yBlPBIXNLzzO7arp 6/lU6O5jDaSFRVKeKZ4qYSsc3GvN81XV+d9go6R3WR964xK4JdEkyt9Hntr1H0Hh lBwyhSWH4nWnsXunc4GepRPVw+cdnOQdrj6T68bqLM5Gd6XWjh88WIDXqLynH6Kn OBBBP/lOD7Su3antNkjnlaX9TP6BF8rNQePWne3AzzA= =ca1M -----END PGP SIGNATURE----- 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 ..
This commit is contained in:
commit
3ef2bc099d
@ -1,7 +1,7 @@
|
||||
Device-Tree bindings for Atmel's HLCDC (High LCD Controller) DRM driver
|
||||
|
||||
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:
|
||||
- compatible: value should be "atmel,hlcdc-display-controller"
|
||||
|
@ -193,6 +193,8 @@ Optional properties:
|
||||
- region-freeze-timeout-us : The maximum time in microseconds to wait for
|
||||
bridges to successfully become disabled before the region has been
|
||||
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.
|
||||
|
||||
In the example below, when an overlay is applied targeting fpga-region0,
|
||||
|
@ -0,0 +1,36 @@
|
||||
* 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:
|
||||
|
||||
The HLCDC IP exposes two subdevices:
|
||||
- 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:
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
MOXA ART Ethernet Controller
|
||||
Faraday Ethernet Controller
|
||||
|
||||
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
|
||||
- interrupts : Should contain the mac interrupt number
|
||||
|
@ -80,6 +80,7 @@ denx Denx Software Engineering
|
||||
devantech Devantech, Ltd.
|
||||
digi Digi International Inc.
|
||||
digilent Diglent, Inc.
|
||||
dioo Dioo Microcircuit Co., Ltd
|
||||
dlg Dialog Semiconductor
|
||||
dlink D-Link Corporation
|
||||
dmo Data Modul AG
|
||||
@ -215,6 +216,7 @@ newhaven Newhaven Display International
|
||||
ni National Instruments
|
||||
nintendo Nintendo
|
||||
nokia Nokia
|
||||
nordic Nordic Semiconductor
|
||||
nuvoton Nuvoton Technology Corporation
|
||||
nvd New Vision Display
|
||||
nvidia NVIDIA
|
||||
@ -261,6 +263,7 @@ richtek Richtek Technology Corporation
|
||||
ricoh Ricoh Co. Ltd.
|
||||
rikomagic Rikomagic Tech Corp. Ltd
|
||||
rockchip Fuzhou Rockchip Electronics Co., Ltd
|
||||
rohm ROHM Semiconductor Co., Ltd
|
||||
samsung Samsung Semiconductor
|
||||
samtec Samtec/Softing company
|
||||
sandisk Sandisk Corporation
|
||||
|
@ -410,10 +410,7 @@ static ssize_t name_show(struct device *dev,
|
||||
static ssize_t modalias_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2);
|
||||
buf[len] = '\n';
|
||||
buf[len+1] = 0;
|
||||
return len+1;
|
||||
return of_device_modalias(dev, buf, PAGE_SIZE);
|
||||
}
|
||||
|
||||
static struct device_attribute ibmebus_bus_device_attrs[] = {
|
||||
|
@ -847,7 +847,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
int len;
|
||||
|
||||
len = of_device_get_modalias(dev, buf, PAGE_SIZE -1);
|
||||
len = of_device_modalias(dev, buf, PAGE_SIZE);
|
||||
if (len != -ENODEV)
|
||||
return len;
|
||||
|
||||
|
@ -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,
|
||||
char *buf)
|
||||
{
|
||||
int len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2);
|
||||
|
||||
buf[len] = '\n';
|
||||
buf[len+1] = 0;
|
||||
|
||||
return len+1;
|
||||
return of_device_modalias(dev, buf, PAGE_SIZE);
|
||||
}
|
||||
|
||||
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,
|
||||
if (!parser->range || parser->range + parser->np > parser->end)
|
||||
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->pci_addr = of_read_number(parser->range + 1, ns);
|
||||
range->cpu_addr = of_translate_address(parser->node,
|
||||
|
@ -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 *child;
|
||||
const phandle *handle;
|
||||
struct device_node *child, *cache_node;
|
||||
|
||||
handle = of_get_property(np, "l2-cache", NULL);
|
||||
if (!handle)
|
||||
handle = of_get_property(np, "next-level-cache", NULL);
|
||||
cache_node = of_parse_phandle(np, "l2-cache", 0);
|
||||
if (!cache_node)
|
||||
cache_node = of_parse_phandle(np, "next-level-cache", 0);
|
||||
|
||||
if (handle)
|
||||
return of_find_node_by_phandle(be32_to_cpup(handle));
|
||||
if (cache_node)
|
||||
return cache_node;
|
||||
|
||||
/* OF on pmac has nodes instead of properties named "l2-cache"
|
||||
* beneath CPU nodes.
|
||||
|
@ -176,7 +176,7 @@ const void *of_device_get_match_data(const struct device *dev)
|
||||
}
|
||||
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;
|
||||
int cplen, i;
|
||||
@ -223,9 +223,8 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
|
||||
str[i] = '_';
|
||||
}
|
||||
|
||||
return tsize;
|
||||
return repend;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_device_get_modalias);
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include <asm/setup.h> /* for COMMAND_LINE_SIZE */
|
||||
#include <asm/page.h>
|
||||
|
||||
#include "of_private.h"
|
||||
|
||||
/*
|
||||
* of_fdt_limit_memory - limit the number of regions in the /memory node
|
||||
* @limit: maximum entries
|
||||
@ -46,8 +48,8 @@ void of_fdt_limit_memory(int limit)
|
||||
const void *val;
|
||||
int nr_address_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
|
||||
int nr_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
|
||||
const uint32_t *addr_prop;
|
||||
const uint32_t *size_prop;
|
||||
const __be32 *addr_prop;
|
||||
const __be32 *size_prop;
|
||||
int root_offset;
|
||||
int cell_size;
|
||||
|
||||
@ -469,11 +471,11 @@ static int unflatten_dt_nodes(const void *blob,
|
||||
* Returns NULL on failure or the memory chunk containing the unflattened
|
||||
* device tree on success.
|
||||
*/
|
||||
static void *__unflatten_device_tree(const void *blob,
|
||||
struct device_node *dad,
|
||||
struct device_node **mynodes,
|
||||
void *(*dt_alloc)(u64 size, u64 align),
|
||||
bool detached)
|
||||
void *__unflatten_device_tree(const void *blob,
|
||||
struct device_node *dad,
|
||||
struct device_node **mynodes,
|
||||
void *(*dt_alloc)(u64 size, u64 align),
|
||||
bool detached)
|
||||
{
|
||||
int size;
|
||||
void *mem;
|
||||
@ -1261,6 +1263,8 @@ void __init unflatten_device_tree(void)
|
||||
|
||||
/* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
|
||||
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)
|
||||
struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
|
||||
__be32 initial_match_array[MAX_PHANDLE_ARGS];
|
||||
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;
|
||||
int imaplen, match, i, rc = -EINVAL;
|
||||
|
||||
|
@ -57,6 +57,8 @@ static void __init of_numa_parse_cpu_nodes(void)
|
||||
else
|
||||
node_set(nid, numa_nodes_parsed);
|
||||
}
|
||||
|
||||
of_node_put(cpus);
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
#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.
|
||||
*
|
||||
|
@ -197,7 +197,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem)
|
||||
const struct of_device_id *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;
|
||||
|
||||
if (!of_flat_dt_is_compatible(rmem->fdt_node, compat))
|
||||
|
@ -92,7 +92,7 @@ static void adjust_overlay_phandles(struct device_node *overlay,
|
||||
if (phandle == OF_PHANDLE_ILLEGAL)
|
||||
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)
|
||||
|
@ -1,7 +1,18 @@
|
||||
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 += overlay.dtb overlay.dtb.S
|
||||
targets += overlay_bad_phandle.dtb overlay_bad_phandle.dtb.S
|
||||
targets += overlay_base.dtb overlay_base.dtb.S
|
||||
|
||||
.SECONDARY: \
|
||||
$(obj)/testcases.dtb.S \
|
||||
$(obj)/testcases.dtb
|
||||
.PRECIOUS: \
|
||||
$(obj)/%.dtb.S \
|
||||
$(obj)/%.dtb
|
||||
|
||||
# enable creation of __symbols__ node
|
||||
DTC_FLAGS_overlay := -@
|
||||
DTC_FLAGS_overlay_bad_phandle := -@
|
||||
DTC_FLAGS_overlay_base := -@
|
||||
|
53
drivers/of/unittest-data/overlay.dts
Normal file
53
drivers/of/unittest-data/overlay.dts
Normal file
@ -0,0 +1,53 @@
|
||||
/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 >;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
20
drivers/of/unittest-data/overlay_bad_phandle.dts
Normal file
20
drivers/of/unittest-data/overlay_bad_phandle.dts
Normal file
@ -0,0 +1,20 @@
|
||||
/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 >;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
80
drivers/of/unittest-data/overlay_base.dts
Normal file
80
drivers/of/unittest-data/overlay_base.dts
Normal file
@ -0,0 +1,80 @@
|
||||
/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 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/hashtable.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_irq.h>
|
||||
@ -1925,6 +1926,324 @@ out:
|
||||
static inline void __init of_unittest_overlay(void) { }
|
||||
#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)
|
||||
{
|
||||
struct device_node *np;
|
||||
@ -1962,6 +2281,8 @@ static int __init of_unittest(void)
|
||||
/* Double check linkage after removing testcase data */
|
||||
of_unittest_check_tree_linkage();
|
||||
|
||||
of_unittest_overlay_high_level();
|
||||
|
||||
pr_info("end of unittest - %i passed, %i failed\n",
|
||||
unittest_results.passed, unittest_results.failed);
|
||||
|
||||
|
@ -224,10 +224,7 @@ static int serdev_drv_remove(struct device *dev)
|
||||
static ssize_t modalias_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2);
|
||||
buf[len] = '\n';
|
||||
buf[len+1] = 0;
|
||||
return len+1;
|
||||
return of_device_modalias(dev, buf, PAGE_SIZE);
|
||||
}
|
||||
|
||||
static struct device_attribute serdev_device_attrs[] = {
|
||||
|
@ -107,7 +107,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
|
||||
int len;
|
||||
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)
|
||||
return len;
|
||||
|
||||
|
@ -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 ssize_t of_device_get_modalias(struct device *dev,
|
||||
char *str, ssize_t len);
|
||||
extern ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len);
|
||||
extern int of_device_request_module(struct device *dev);
|
||||
|
||||
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)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int of_device_get_modalias(struct device *dev,
|
||||
char *str, ssize_t len)
|
||||
static inline int of_device_modalias(struct device *dev,
|
||||
char *str, ssize_t len)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <linux/ioport.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
|
||||
|
@ -280,9 +280,21 @@ DTC ?= $(objtree)/scripts/dtc/dtc
|
||||
|
||||
# Disable noisy checks by default
|
||||
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
|
||||
|
||||
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
|
||||
quiet_cmd_dt_S_dtb= DTB $@
|
||||
cmd_dt_S_dtb= \
|
||||
|
@ -72,17 +72,16 @@ struct check {
|
||||
#define CHECK(_nm, _fn, _d, ...) \
|
||||
CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__)
|
||||
|
||||
#ifdef __GNUC__
|
||||
static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
|
||||
#endif
|
||||
static inline void check_msg(struct check *c, const char *fmt, ...)
|
||||
static inline void PRINTF(3, 4) check_msg(struct check *c, struct dt_info *dti,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
if ((c->warn && (quiet < 1))
|
||||
|| (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);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, "\n");
|
||||
@ -90,11 +89,11 @@ static inline void check_msg(struct check *c, const char *fmt, ...)
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#define FAIL(c, ...) \
|
||||
do { \
|
||||
TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
|
||||
(c)->status = FAILED; \
|
||||
check_msg((c), __VA_ARGS__); \
|
||||
#define FAIL(c, dti, ...) \
|
||||
do { \
|
||||
TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
|
||||
(c)->status = FAILED; \
|
||||
check_msg((c), dti, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
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)
|
||||
error = error || run_check(prq, dti);
|
||||
if (prq->status != PASSED) {
|
||||
c->status = PREREQ;
|
||||
check_msg(c, "Failed prerequisite '%s'",
|
||||
check_msg(c, dti, "Failed prerequisite '%s'",
|
||||
c->prereq[i]->name);
|
||||
}
|
||||
}
|
||||
@ -157,7 +156,7 @@ out:
|
||||
static inline void check_always_fail(struct check *c, struct dt_info *dti,
|
||||
struct node *node)
|
||||
{
|
||||
FAIL(c, "always_fail check");
|
||||
FAIL(c, dti, "always_fail check");
|
||||
}
|
||||
CHECK(always_fail, check_always_fail, NULL);
|
||||
|
||||
@ -172,7 +171,7 @@ static void check_is_string(struct check *c, struct dt_info *dti,
|
||||
return; /* Not present, assumed ok */
|
||||
|
||||
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);
|
||||
}
|
||||
#define WARNING_IF_NOT_STRING(nm, propname) \
|
||||
@ -191,7 +190,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti,
|
||||
return; /* Not present, assumed ok */
|
||||
|
||||
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);
|
||||
}
|
||||
#define WARNING_IF_NOT_CELL(nm, propname) \
|
||||
@ -213,7 +212,7 @@ static void check_duplicate_node_names(struct check *c, struct dt_info *dti,
|
||||
child2;
|
||||
child2 = child2->next_sibling)
|
||||
if (streq(child->name, child2->name))
|
||||
FAIL(c, "Duplicate node name %s",
|
||||
FAIL(c, dti, "Duplicate node name %s",
|
||||
child->fullpath);
|
||||
}
|
||||
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,
|
||||
if (prop2->deleted)
|
||||
continue;
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -239,6 +238,7 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
|
||||
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
#define DIGITS "0123456789"
|
||||
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
|
||||
#define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
|
||||
|
||||
static void check_node_name_chars(struct check *c, struct dt_info *dti,
|
||||
struct node *node)
|
||||
@ -246,16 +246,27 @@ static void check_node_name_chars(struct check *c, struct dt_info *dti,
|
||||
int n = strspn(node->name, c->data);
|
||||
|
||||
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);
|
||||
}
|
||||
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,
|
||||
struct node *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);
|
||||
}
|
||||
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,
|
||||
|
||||
if (prop) {
|
||||
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);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -293,12 +304,44 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
|
||||
int n = strspn(prop->name, c->data);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
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_ARGS(node,prop,mark) \
|
||||
((mark) ? "value of " : ""), \
|
||||
@ -327,7 +370,7 @@ static void check_duplicate_label(struct check *c, struct dt_info *dti,
|
||||
return;
|
||||
|
||||
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,
|
||||
label, DESCLABEL_ARGS(node, prop, mark),
|
||||
DESCLABEL_ARGS(othernode, otherprop, othermark));
|
||||
@ -367,7 +410,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
|
||||
return 0;
|
||||
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
@ -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
|
||||
* other node's phandle". That's nonsensical
|
||||
* 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);
|
||||
}
|
||||
/* 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,
|
||||
phandle = propval_cell(prop);
|
||||
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
@ -420,7 +463,7 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti,
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
if (linux_phandle && !phandle)
|
||||
@ -428,7 +471,7 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti,
|
||||
|
||||
other = get_node_by_phandle(root, phandle);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
@ -453,7 +496,7 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
|
||||
|
||||
if ((prop->val.len != node->basenamelen+1)
|
||||
|| (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);
|
||||
} else {
|
||||
/* The name property is correct, and therefore redundant.
|
||||
@ -488,16 +531,16 @@ static void fixup_phandle_references(struct check *c, struct dt_info *dti,
|
||||
refnode = get_node_by_ref(dt, m->ref);
|
||||
if (! refnode) {
|
||||
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);
|
||||
else /* mark the entry as unresolved */
|
||||
*((cell_t *)(prop->val.val + m->offset)) =
|
||||
*((fdt32_t *)(prop->val.val + m->offset)) =
|
||||
cpu_to_fdt32(0xffffffff);
|
||||
continue;
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
refnode = get_node_by_ref(dt, m->ref);
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
@ -579,19 +622,19 @@ static void check_reg_format(struct check *c, struct dt_info *dti,
|
||||
return; /* No "reg", that's fine */
|
||||
|
||||
if (!node->parent) {
|
||||
FAIL(c, "Root node has a \"reg\" property");
|
||||
FAIL(c, dti, "Root node has a \"reg\" property");
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
size_cells = node_size_cells(node->parent);
|
||||
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
|
||||
|
||||
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)",
|
||||
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,
|
||||
return;
|
||||
|
||||
if (!node->parent) {
|
||||
FAIL(c, "Root node has a \"ranges\" property");
|
||||
FAIL(c, dti, "Root node has a \"ranges\" property");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -620,17 +663,17 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
|
||||
|
||||
if (prop->val.len == 0) {
|
||||
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)",
|
||||
node->fullpath, c_addr_cells, node->parent->fullpath,
|
||||
p_addr_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)",
|
||||
node->fullpath, c_size_cells, node->parent->fullpath,
|
||||
p_size_cells);
|
||||
} 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, "
|
||||
"#size-cells == %d)", node->fullpath, prop->val.len,
|
||||
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,
|
||||
}
|
||||
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, ®_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, ®_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, ®_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
|
||||
*/
|
||||
@ -656,11 +922,11 @@ static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti,
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
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,
|
||||
|
||||
prop = get_property(chosen, "interrupt-controller");
|
||||
if (prop)
|
||||
FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
|
||||
FAIL(c, dti, "/chosen has obsolete \"interrupt-controller\" "
|
||||
"property");
|
||||
}
|
||||
WARNING(obsolete_chosen_interrupt_controller,
|
||||
@ -703,9 +969,20 @@ static struct check *check_table[] = {
|
||||
&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
|
||||
&device_type_is_string, &model_is_string, &status_is_string,
|
||||
|
||||
&property_name_chars_strict,
|
||||
&node_name_chars_strict,
|
||||
|
||||
&addr_size_cells, ®_format, &ranges_format,
|
||||
|
||||
&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,
|
||||
&obsolete_chosen_interrupt_controller,
|
||||
|
@ -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)
|
||||
{
|
||||
uint8_t value_8;
|
||||
uint16_t value_16;
|
||||
uint32_t value_32;
|
||||
uint64_t value_64;
|
||||
fdt16_t value_16;
|
||||
fdt32_t value_32;
|
||||
fdt64_t value_64;
|
||||
|
||||
switch (bits) {
|
||||
case 8:
|
||||
@ -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);
|
||||
bere.size = cpu_to_fdt64(re->size);
|
||||
re.address = cpu_to_fdt64(address);
|
||||
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)
|
||||
|
@ -62,7 +62,8 @@ static int dts_version = 1;
|
||||
|
||||
static void push_input_file(const char *filename);
|
||||
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;
|
||||
|
||||
static void push_input_file(const char *filename);
|
||||
static bool pop_input_file(void);
|
||||
static void lexical_error(const char *fmt, ...);
|
||||
#line 660 "dtc-lexer.lex.c"
|
||||
static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
|
||||
|
||||
#line 661 "dtc-lexer.lex.c"
|
||||
|
||||
#define INITIAL 0
|
||||
#define BYTESTRING 1
|
||||
@ -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 */
|
||||
{
|
||||
@ -937,7 +938,7 @@ do_action: /* This label is used only to access EOF actions. */
|
||||
case 1:
|
||||
/* rule 1 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 69 "dtc-lexer.l"
|
||||
#line 70 "dtc-lexer.l"
|
||||
{
|
||||
char *name = strchr(yytext, '\"') + 1;
|
||||
yytext[yyleng-1] = '\0';
|
||||
@ -947,7 +948,7 @@ YY_RULE_SETUP
|
||||
case 2:
|
||||
/* rule 2 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 75 "dtc-lexer.l"
|
||||
#line 76 "dtc-lexer.l"
|
||||
{
|
||||
char *line, *fnstart, *fnend;
|
||||
struct data fn;
|
||||
@ -981,7 +982,7 @@ case YY_STATE_EOF(INITIAL):
|
||||
case YY_STATE_EOF(BYTESTRING):
|
||||
case YY_STATE_EOF(PROPNODENAME):
|
||||
case YY_STATE_EOF(V1):
|
||||
#line 104 "dtc-lexer.l"
|
||||
#line 105 "dtc-lexer.l"
|
||||
{
|
||||
if (!pop_input_file()) {
|
||||
yyterminate();
|
||||
@ -991,7 +992,7 @@ case YY_STATE_EOF(V1):
|
||||
case 3:
|
||||
/* rule 3 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 110 "dtc-lexer.l"
|
||||
#line 111 "dtc-lexer.l"
|
||||
{
|
||||
DPRINT("String: %s\n", yytext);
|
||||
yylval.data = data_copy_escape_string(yytext+1,
|
||||
@ -1001,7 +1002,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 4:
|
||||
YY_RULE_SETUP
|
||||
#line 117 "dtc-lexer.l"
|
||||
#line 118 "dtc-lexer.l"
|
||||
{
|
||||
DPRINT("Keyword: /dts-v1/\n");
|
||||
dts_version = 1;
|
||||
@ -1011,7 +1012,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 5:
|
||||
YY_RULE_SETUP
|
||||
#line 124 "dtc-lexer.l"
|
||||
#line 125 "dtc-lexer.l"
|
||||
{
|
||||
DPRINT("Keyword: /plugin/\n");
|
||||
return DT_PLUGIN;
|
||||
@ -1019,7 +1020,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 6:
|
||||
YY_RULE_SETUP
|
||||
#line 129 "dtc-lexer.l"
|
||||
#line 130 "dtc-lexer.l"
|
||||
{
|
||||
DPRINT("Keyword: /memreserve/\n");
|
||||
BEGIN_DEFAULT();
|
||||
@ -1028,7 +1029,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 7:
|
||||
YY_RULE_SETUP
|
||||
#line 135 "dtc-lexer.l"
|
||||
#line 136 "dtc-lexer.l"
|
||||
{
|
||||
DPRINT("Keyword: /bits/\n");
|
||||
BEGIN_DEFAULT();
|
||||
@ -1037,7 +1038,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 8:
|
||||
YY_RULE_SETUP
|
||||
#line 141 "dtc-lexer.l"
|
||||
#line 142 "dtc-lexer.l"
|
||||
{
|
||||
DPRINT("Keyword: /delete-property/\n");
|
||||
DPRINT("<PROPNODENAME>\n");
|
||||
@ -1047,7 +1048,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 9:
|
||||
YY_RULE_SETUP
|
||||
#line 148 "dtc-lexer.l"
|
||||
#line 149 "dtc-lexer.l"
|
||||
{
|
||||
DPRINT("Keyword: /delete-node/\n");
|
||||
DPRINT("<PROPNODENAME>\n");
|
||||
@ -1057,7 +1058,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 10:
|
||||
YY_RULE_SETUP
|
||||
#line 155 "dtc-lexer.l"
|
||||
#line 156 "dtc-lexer.l"
|
||||
{
|
||||
DPRINT("Label: %s\n", yytext);
|
||||
yylval.labelref = xstrdup(yytext);
|
||||
@ -1067,7 +1068,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 11:
|
||||
YY_RULE_SETUP
|
||||
#line 162 "dtc-lexer.l"
|
||||
#line 163 "dtc-lexer.l"
|
||||
{
|
||||
char *e;
|
||||
DPRINT("Integer Literal: '%s'\n", yytext);
|
||||
@ -1093,7 +1094,7 @@ YY_RULE_SETUP
|
||||
case 12:
|
||||
/* rule 12 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 184 "dtc-lexer.l"
|
||||
#line 185 "dtc-lexer.l"
|
||||
{
|
||||
struct data d;
|
||||
DPRINT("Character literal: %s\n", yytext);
|
||||
@ -1117,7 +1118,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 13:
|
||||
YY_RULE_SETUP
|
||||
#line 205 "dtc-lexer.l"
|
||||
#line 206 "dtc-lexer.l"
|
||||
{ /* label reference */
|
||||
DPRINT("Ref: %s\n", yytext+1);
|
||||
yylval.labelref = xstrdup(yytext+1);
|
||||
@ -1126,7 +1127,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 14:
|
||||
YY_RULE_SETUP
|
||||
#line 211 "dtc-lexer.l"
|
||||
#line 212 "dtc-lexer.l"
|
||||
{ /* new-style path reference */
|
||||
yytext[yyleng-1] = '\0';
|
||||
DPRINT("Ref: %s\n", yytext+2);
|
||||
@ -1136,7 +1137,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 15:
|
||||
YY_RULE_SETUP
|
||||
#line 218 "dtc-lexer.l"
|
||||
#line 219 "dtc-lexer.l"
|
||||
{
|
||||
yylval.byte = strtol(yytext, NULL, 16);
|
||||
DPRINT("Byte: %02x\n", (int)yylval.byte);
|
||||
@ -1145,7 +1146,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 16:
|
||||
YY_RULE_SETUP
|
||||
#line 224 "dtc-lexer.l"
|
||||
#line 225 "dtc-lexer.l"
|
||||
{
|
||||
DPRINT("/BYTESTRING\n");
|
||||
BEGIN_DEFAULT();
|
||||
@ -1154,7 +1155,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 17:
|
||||
YY_RULE_SETUP
|
||||
#line 230 "dtc-lexer.l"
|
||||
#line 231 "dtc-lexer.l"
|
||||
{
|
||||
DPRINT("PropNodeName: %s\n", yytext);
|
||||
yylval.propnodename = xstrdup((yytext[0] == '\\') ?
|
||||
@ -1165,7 +1166,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 18:
|
||||
YY_RULE_SETUP
|
||||
#line 238 "dtc-lexer.l"
|
||||
#line 239 "dtc-lexer.l"
|
||||
{
|
||||
DPRINT("Binary Include\n");
|
||||
return DT_INCBIN;
|
||||
@ -1174,64 +1175,64 @@ YY_RULE_SETUP
|
||||
case 19:
|
||||
/* rule 19 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 243 "dtc-lexer.l"
|
||||
#line 244 "dtc-lexer.l"
|
||||
/* eat whitespace */
|
||||
YY_BREAK
|
||||
case 20:
|
||||
/* rule 20 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 244 "dtc-lexer.l"
|
||||
#line 245 "dtc-lexer.l"
|
||||
/* eat C-style comments */
|
||||
YY_BREAK
|
||||
case 21:
|
||||
/* rule 21 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 245 "dtc-lexer.l"
|
||||
#line 246 "dtc-lexer.l"
|
||||
/* eat C++-style comments */
|
||||
YY_BREAK
|
||||
case 22:
|
||||
YY_RULE_SETUP
|
||||
#line 247 "dtc-lexer.l"
|
||||
#line 248 "dtc-lexer.l"
|
||||
{ return DT_LSHIFT; };
|
||||
YY_BREAK
|
||||
case 23:
|
||||
YY_RULE_SETUP
|
||||
#line 248 "dtc-lexer.l"
|
||||
#line 249 "dtc-lexer.l"
|
||||
{ return DT_RSHIFT; };
|
||||
YY_BREAK
|
||||
case 24:
|
||||
YY_RULE_SETUP
|
||||
#line 249 "dtc-lexer.l"
|
||||
#line 250 "dtc-lexer.l"
|
||||
{ return DT_LE; };
|
||||
YY_BREAK
|
||||
case 25:
|
||||
YY_RULE_SETUP
|
||||
#line 250 "dtc-lexer.l"
|
||||
#line 251 "dtc-lexer.l"
|
||||
{ return DT_GE; };
|
||||
YY_BREAK
|
||||
case 26:
|
||||
YY_RULE_SETUP
|
||||
#line 251 "dtc-lexer.l"
|
||||
#line 252 "dtc-lexer.l"
|
||||
{ return DT_EQ; };
|
||||
YY_BREAK
|
||||
case 27:
|
||||
YY_RULE_SETUP
|
||||
#line 252 "dtc-lexer.l"
|
||||
#line 253 "dtc-lexer.l"
|
||||
{ return DT_NE; };
|
||||
YY_BREAK
|
||||
case 28:
|
||||
YY_RULE_SETUP
|
||||
#line 253 "dtc-lexer.l"
|
||||
#line 254 "dtc-lexer.l"
|
||||
{ return DT_AND; };
|
||||
YY_BREAK
|
||||
case 29:
|
||||
YY_RULE_SETUP
|
||||
#line 254 "dtc-lexer.l"
|
||||
#line 255 "dtc-lexer.l"
|
||||
{ return DT_OR; };
|
||||
YY_BREAK
|
||||
case 30:
|
||||
YY_RULE_SETUP
|
||||
#line 256 "dtc-lexer.l"
|
||||
#line 257 "dtc-lexer.l"
|
||||
{
|
||||
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
|
||||
(unsigned)yytext[0]);
|
||||
@ -1249,10 +1250,10 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 31:
|
||||
YY_RULE_SETUP
|
||||
#line 271 "dtc-lexer.l"
|
||||
#line 272 "dtc-lexer.l"
|
||||
ECHO;
|
||||
YY_BREAK
|
||||
#line 1256 "dtc-lexer.lex.c"
|
||||
#line 1257 "dtc-lexer.lex.c"
|
||||
|
||||
case YY_END_OF_BUFFER:
|
||||
{
|
||||
@ -2218,7 +2219,7 @@ void yyfree (void * ptr )
|
||||
|
||||
#define YYTABLES_NAME "yytables"
|
||||
|
||||
#line 271 "dtc-lexer.l"
|
||||
#line 272 "dtc-lexer.l"
|
||||
|
||||
|
||||
|
||||
|
@ -1557,10 +1557,10 @@ yyreduce:
|
||||
{
|
||||
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));
|
||||
else
|
||||
} else
|
||||
ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref));
|
||||
(yyval.node) = (yyvsp[-3].node);
|
||||
}
|
||||
|
@ -171,10 +171,10 @@ devicetree:
|
||||
{
|
||||
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);
|
||||
else
|
||||
} else
|
||||
ERROR(&@3, "Label or path %s not found", $3);
|
||||
$$ = $1;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
struct stat statbuf;
|
||||
uint32_t magic;
|
||||
fdt32_t magic;
|
||||
FILE *f;
|
||||
|
||||
if (stat(fname, &statbuf) != 0)
|
||||
@ -159,8 +159,7 @@ static const char *guess_input_format(const char *fname, const char *fallback)
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
magic = fdt32_to_cpu(magic);
|
||||
if (magic == FDT_MAGIC)
|
||||
if (fdt32_to_cpu(magic) == FDT_MAGIC)
|
||||
return "dtb";
|
||||
|
||||
return guess_type_by_name(fname, fallback);
|
||||
@ -216,7 +215,7 @@ int main(int argc, char *argv[])
|
||||
alignsize = strtol(optarg, NULL, 0);
|
||||
if (!is_power_of_2(alignsize))
|
||||
die("Invalid argument \"%d\" to -a option\n",
|
||||
optarg);
|
||||
alignsize);
|
||||
break;
|
||||
case 'f':
|
||||
force = true;
|
||||
@ -309,6 +308,8 @@ int main(int argc, char *argv[])
|
||||
else
|
||||
die("Unknown input format \"%s\"\n", inform);
|
||||
|
||||
dti->outname = outname;
|
||||
|
||||
if (depfile) {
|
||||
fputc('\n', depfile);
|
||||
fclose(depfile);
|
||||
|
@ -43,7 +43,6 @@
|
||||
#define debug(...)
|
||||
#endif
|
||||
|
||||
|
||||
#define DEFAULT_FDT_VERSION 17
|
||||
|
||||
/*
|
||||
@ -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_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_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_byte(struct data d, uint8_t byte);
|
||||
struct data data_append_zeroes(struct data d, int len);
|
||||
@ -136,6 +135,10 @@ struct label {
|
||||
struct label *next;
|
||||
};
|
||||
|
||||
struct bus_type {
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct property {
|
||||
bool deleted;
|
||||
char *name;
|
||||
@ -162,6 +165,7 @@ struct node {
|
||||
int addr_cells, size_cells;
|
||||
|
||||
struct label *labels;
|
||||
const struct bus_type *bus;
|
||||
};
|
||||
|
||||
#define for_each_label_withdel(l0, l) \
|
||||
@ -227,7 +231,7 @@ uint32_t guess_boot_cpuid(struct node *tree);
|
||||
/* Boot info (tree plus memreserve information */
|
||||
|
||||
struct reserve_info {
|
||||
struct fdt_reserve_entry re;
|
||||
uint64_t address, size;
|
||||
|
||||
struct reserve_info *next;
|
||||
|
||||
@ -246,6 +250,7 @@ struct dt_info {
|
||||
struct reserve_info *reservelist;
|
||||
uint32_t boot_cpuid_phys;
|
||||
struct node *dt; /* the device tree */
|
||||
const char *outname; /* filename being written to, "-" for stdout */
|
||||
};
|
||||
|
||||
/* DTS version flags definitions */
|
||||
|
@ -49,7 +49,7 @@ static struct version_info {
|
||||
|
||||
struct emitter {
|
||||
void (*cell)(void *, cell_t);
|
||||
void (*string)(void *, char *, int);
|
||||
void (*string)(void *, const char *, int);
|
||||
void (*align)(void *, int);
|
||||
void (*data)(void *, struct data);
|
||||
void (*beginnode)(void *, struct label *labels);
|
||||
@ -64,7 +64,7 @@ static void bin_emit_cell(void *e, cell_t 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;
|
||||
|
||||
@ -144,22 +144,14 @@ static void asm_emit_cell(void *e, cell_t val)
|
||||
(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;
|
||||
char c = 0;
|
||||
|
||||
if (len != 0) {
|
||||
/* XXX: ewww */
|
||||
c = str[len];
|
||||
str[len] = '\0';
|
||||
}
|
||||
|
||||
fprintf(f, "\t.string\t\"%s\"\n", str);
|
||||
|
||||
if (len != 0) {
|
||||
str[len] = c;
|
||||
}
|
||||
if (len != 0)
|
||||
fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
|
||||
else
|
||||
fprintf(f, "\t.string\t\"%s\"\n", str);
|
||||
}
|
||||
|
||||
static void asm_emit_align(void *e, int a)
|
||||
@ -179,7 +171,7 @@ static void asm_emit_data(void *e, struct data d)
|
||||
emit_offset_label(f, m->ref, m->offset);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -318,17 +310,16 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
|
||||
{
|
||||
struct reserve_info *re;
|
||||
struct data d = empty_data;
|
||||
static struct fdt_reserve_entry null_re = {0,0};
|
||||
int j;
|
||||
|
||||
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.
|
||||
*/
|
||||
for (j = 0; j < reservenum; j++) {
|
||||
d = data_append_re(d, &null_re);
|
||||
d = data_append_re(d, 0, 0);
|
||||
}
|
||||
|
||||
return d;
|
||||
@ -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, "%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",
|
||||
(unsigned int)(re->re.address & 0xffffffff));
|
||||
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32));
|
||||
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff));
|
||||
(unsigned int)(re->address & 0xffffffff));
|
||||
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32));
|
||||
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff));
|
||||
}
|
||||
for (i = 0; i < reservenum; i++) {
|
||||
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)
|
||||
|
||||
static uint32_t flat_read_word(struct inbuf *inb)
|
||||
{
|
||||
uint32_t val;
|
||||
fdt32_t val;
|
||||
|
||||
assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
|
||||
|
||||
@ -718,13 +709,15 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
|
||||
* First pass, count entries.
|
||||
*/
|
||||
while (1) {
|
||||
uint64_t address, size;
|
||||
|
||||
flat_read_chunk(inb, &re, sizeof(re));
|
||||
re.address = fdt64_to_cpu(re.address);
|
||||
re.size = fdt64_to_cpu(re.size);
|
||||
if (re.size == 0)
|
||||
address = fdt64_to_cpu(re.address);
|
||||
size = fdt64_to_cpu(re.size);
|
||||
if (size == 0)
|
||||
break;
|
||||
|
||||
new = build_reserve_entry(re.address, re.size);
|
||||
new = build_reserve_entry(address, size);
|
||||
reservelist = add_reserve_entry(reservelist, new);
|
||||
}
|
||||
|
||||
@ -817,6 +810,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
|
||||
struct dt_info *dt_from_blob(const char *fname)
|
||||
{
|
||||
FILE *f;
|
||||
fdt32_t magic_buf, totalsize_buf;
|
||||
uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
|
||||
uint32_t off_dt, off_str, off_mem_rsvmap;
|
||||
int rc;
|
||||
@ -833,7 +827,7 @@ struct dt_info *dt_from_blob(const char *fname)
|
||||
|
||||
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))
|
||||
die("Error reading DT blob magic number: %s\n",
|
||||
strerror(errno));
|
||||
@ -844,11 +838,11 @@ struct dt_info *dt_from_blob(const char *fname)
|
||||
die("Mysterious short read reading magic number\n");
|
||||
}
|
||||
|
||||
magic = fdt32_to_cpu(magic);
|
||||
magic = fdt32_to_cpu(magic_buf);
|
||||
if (magic != FDT_MAGIC)
|
||||
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))
|
||||
die("Error reading DT blob size: %s\n", strerror(errno));
|
||||
if (rc < 1) {
|
||||
@ -858,7 +852,7 @@ struct dt_info *dt_from_blob(const char *fname)
|
||||
die("Mysterious short read reading blob size\n");
|
||||
}
|
||||
|
||||
totalsize = fdt32_to_cpu(totalsize);
|
||||
totalsize = fdt32_to_cpu(totalsize_buf);
|
||||
if (totalsize < FDT_V1_SIZE)
|
||||
die("DT blob size (%d) is too small\n", totalsize);
|
||||
|
||||
|
@ -283,7 +283,8 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memcpy(prop->data, val, len);
|
||||
if (len)
|
||||
memcpy(prop->data, val, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,9 @@
|
||||
/* 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);
|
||||
#endif
|
||||
static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
|
||||
{
|
||||
return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
|
||||
@ -210,7 +212,6 @@ int fdt_next_subnode(const void *fdt, int offset);
|
||||
/**********************************************************************/
|
||||
/* General functions */
|
||||
/**********************************************************************/
|
||||
|
||||
#define fdt_get_header(fdt, field) \
|
||||
(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
|
||||
#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);
|
||||
* useful for finding subnodes based on a portion of a larger string,
|
||||
* such as a full path.
|
||||
*/
|
||||
#ifndef SWIG /* Not available in Python */
|
||||
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
|
||||
const char *name, int namelen);
|
||||
#endif
|
||||
/**
|
||||
* fdt_subnode_offset - find a subnode of a given node
|
||||
* @fdt: pointer to the device tree blob
|
||||
@ -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
|
||||
* 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);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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,
|
||||
* Identical to fdt_get_property(), but only examine the first namelen
|
||||
* 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,
|
||||
int nodeoffset,
|
||||
const char *name,
|
||||
int namelen, int *lenp);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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,
|
||||
* -FDT_ERR_BADSTRUCTURE,
|
||||
* -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 char **namep, int *lenp);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* fdt_getprop_namelen - get property value based on substring
|
||||
@ -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
|
||||
* 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 char *name, int namelen, int *lenp);
|
||||
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,
|
||||
namelen, lenp);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* fdt_getprop - retrieve the value of a given property
|
||||
@ -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
|
||||
* 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 *name, int namelen);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* fdt_get_alias - retrieve the path referenced by a given alias
|
||||
@ -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
|
||||
* 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,
|
||||
const char *name, int namelen,
|
||||
uint32_t idx, const void *val,
|
||||
int len);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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,
|
||||
* -FDT_ERR_BADSTRUCTURE,
|
||||
* -FDT_ERR_TRUNCATED, standard meanings
|
||||
*/
|
||||
#ifndef SWIG /* Not available in Python */
|
||||
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
|
||||
const void *val, int len);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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,
|
||||
#define fdt_setprop_string(fdt, nodeoffset, name, str) \
|
||||
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: pointer to the device tree blob
|
||||
@ -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
|
||||
* full path.
|
||||
*/
|
||||
#ifndef SWIG /* Not available in Python */
|
||||
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
||||
const char *name, int namelen);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* fdt_add_subnode - creates a new node
|
||||
|
@ -58,16 +58,16 @@
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __CHECKER__
|
||||
#define __force __attribute__((force))
|
||||
#define __bitwise __attribute__((bitwise))
|
||||
#define FDT_FORCE __attribute__((force))
|
||||
#define FDT_BITWISE __attribute__((bitwise))
|
||||
#else
|
||||
#define __force
|
||||
#define __bitwise
|
||||
#define FDT_FORCE
|
||||
#define FDT_BITWISE
|
||||
#endif
|
||||
|
||||
typedef uint16_t __bitwise fdt16_t;
|
||||
typedef uint32_t __bitwise fdt32_t;
|
||||
typedef uint64_t __bitwise fdt64_t;
|
||||
typedef uint16_t FDT_BITWISE fdt16_t;
|
||||
typedef uint32_t FDT_BITWISE fdt32_t;
|
||||
typedef uint64_t FDT_BITWISE fdt64_t;
|
||||
|
||||
#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))
|
||||
@ -80,29 +80,29 @@ typedef uint64_t __bitwise fdt64_t;
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return (__force fdt64_t)CPU_TO_FDT64(x);
|
||||
return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x);
|
||||
}
|
||||
#undef CPU_TO_FDT64
|
||||
#undef CPU_TO_FDT32
|
||||
|
@ -242,7 +242,7 @@ void delete_property_by_name(struct node *node, char *name)
|
||||
struct property *prop = node->proplist;
|
||||
|
||||
while (prop) {
|
||||
if (!strcmp(prop->name, name)) {
|
||||
if (streq(prop->name, name)) {
|
||||
delete_property(prop);
|
||||
return;
|
||||
}
|
||||
@ -275,7 +275,7 @@ void delete_node_by_name(struct node *parent, char *name)
|
||||
struct node *node = parent->children;
|
||||
|
||||
while (node) {
|
||||
if (!strcmp(node->name, name)) {
|
||||
if (streq(node->name, name)) {
|
||||
delete_node(node);
|
||||
return;
|
||||
}
|
||||
@ -319,8 +319,8 @@ struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
|
||||
|
||||
memset(new, 0, sizeof(*new));
|
||||
|
||||
new->re.address = address;
|
||||
new->re.size = size;
|
||||
new->address = address;
|
||||
new->size = size;
|
||||
|
||||
return new;
|
||||
}
|
||||
@ -393,7 +393,7 @@ struct property *get_property(struct node *node, const char *propname)
|
||||
cell_t propval_cell(struct property *prop)
|
||||
{
|
||||
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,
|
||||
@ -599,13 +599,13 @@ static int cmp_reserve_info(const void *ax, const void *bx)
|
||||
a = *((const struct reserve_info * const *)ax);
|
||||
b = *((const struct reserve_info * const *)bx);
|
||||
|
||||
if (a->re.address < b->re.address)
|
||||
if (a->address < b->address)
|
||||
return -1;
|
||||
else if (a->re.address > b->re.address)
|
||||
else if (a->address > b->address)
|
||||
return 1;
|
||||
else if (a->re.size < b->re.size)
|
||||
else if (a->size < b->size)
|
||||
return -1;
|
||||
else if (a->re.size > b->re.size)
|
||||
else if (a->size > b->size)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
@ -847,6 +847,8 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn,
|
||||
xasprintf(&entry, "%s:%s:%u",
|
||||
node->fullpath, prop->name, m->offset);
|
||||
append_to_property(fn, m->ref, entry, strlen(entry) + 1);
|
||||
|
||||
free(entry);
|
||||
}
|
||||
|
||||
static void generate_fixups_tree_internal(struct dt_info *dti,
|
||||
@ -900,7 +902,7 @@ static void add_local_fixup_entry(struct dt_info *dti,
|
||||
struct node *refnode)
|
||||
{
|
||||
struct node *wn, *nwn; /* local fixup node, walk node, new */
|
||||
uint32_t value_32;
|
||||
fdt32_t value_32;
|
||||
char **compp;
|
||||
int i, depth;
|
||||
|
||||
|
@ -252,7 +252,7 @@ srcpos_string(struct srcpos *pos)
|
||||
const char *fname = "<no-file>";
|
||||
char *pos_str;
|
||||
|
||||
if (pos)
|
||||
if (pos->file && pos->file->name)
|
||||
fname = pos->file->name;
|
||||
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include "util.h"
|
||||
|
||||
struct srcfile_state {
|
||||
FILE *f;
|
||||
@ -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 char *srcpos_string(struct srcpos *pos);
|
||||
|
||||
extern void srcpos_verror(struct srcpos *pos, const char *prefix,
|
||||
const char *fmt, va_list va)
|
||||
__attribute__((format(printf, 3, 0)));
|
||||
extern void srcpos_error(struct srcpos *pos, const char *prefix,
|
||||
const char *fmt, ...)
|
||||
__attribute__((format(printf, 3, 4)));
|
||||
extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix,
|
||||
const char *fmt, va_list va);
|
||||
extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix,
|
||||
const char *fmt, ...);
|
||||
|
||||
extern void srcpos_set_line(char *f, int l);
|
||||
|
||||
|
@ -137,7 +137,7 @@ static void write_propval_string(FILE *f, struct data val)
|
||||
static void write_propval_cells(FILE *f, struct data val)
|
||||
{
|
||||
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;
|
||||
|
||||
fprintf(f, "<");
|
||||
@ -275,8 +275,8 @@ void dt_to_source(FILE *f, struct dt_info *dti)
|
||||
for_each_label(re->labels, l)
|
||||
fprintf(f, "%s: ", l->label);
|
||||
fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
|
||||
(unsigned long long)re->re.address,
|
||||
(unsigned long long)re->re.size);
|
||||
(unsigned long long)re->address,
|
||||
(unsigned long long)re->size);
|
||||
}
|
||||
|
||||
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
|
||||
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"
|
||||
|
||||
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
|
||||
cd $DTC_UPSTREAM_PATH
|
||||
make clean
|
||||
make check
|
||||
dtc_version=$(git describe HEAD)
|
||||
dtc_log=$(git log --oneline ${last_dtc_ver}..)
|
||||
|
||||
|
||||
# Copy the files into the Linux tree
|
||||
cd $DTC_LINUX_PATH
|
||||
@ -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
|
||||
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)
|
||||
} while (s < data + len);
|
||||
|
||||
} else if ((len % 4) == 0) {
|
||||
const uint32_t *cell = (const uint32_t *)data;
|
||||
const fdt32_t *cell = (const fdt32_t *)data;
|
||||
|
||||
printf(" = <");
|
||||
for (i = 0, len /= 4; i < len; i++)
|
||||
@ -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);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void util_usage(const char *errmsg, const char *synopsis,
|
||||
const char *short_opts, struct option const long_opts[],
|
||||
const char * const opts_help[])
|
||||
void NORETURN util_usage(const char *errmsg, const char *synopsis,
|
||||
const char *short_opts,
|
||||
struct option const long_opts[],
|
||||
const char * const opts_help[])
|
||||
{
|
||||
FILE *fp = errmsg ? stderr : stdout;
|
||||
const char a_arg[] = "<arg>";
|
||||
|
@ -25,9 +25,17 @@
|
||||
* 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]))
|
||||
|
||||
static inline void __attribute__((noreturn)) die(const char *str, ...)
|
||||
static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@ -53,13 +61,14 @@ static inline void *xrealloc(void *p, size_t len)
|
||||
void *new = realloc(p, len);
|
||||
|
||||
if (!new)
|
||||
die("realloc() failed (len=%d)\n", len);
|
||||
die("realloc() failed (len=%zd)\n", len);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
@ -188,7 +197,7 @@ void utilfdt_print_data(const char *data, int len);
|
||||
/**
|
||||
* Show source version and exit
|
||||
*/
|
||||
void util_version(void) __attribute__((noreturn));
|
||||
void NORETURN util_version(void);
|
||||
|
||||
/**
|
||||
* Show usage and exit
|
||||
@ -202,9 +211,10 @@ void util_version(void) __attribute__((noreturn));
|
||||
* @param long_opts The structure of long options
|
||||
* @param opts_help An array of help strings (should align with long_opts)
|
||||
*/
|
||||
void util_usage(const char *errmsg, const char *synopsis,
|
||||
const char *short_opts, struct option const long_opts[],
|
||||
const char * const opts_help[]) __attribute__((noreturn));
|
||||
void NORETURN util_usage(const char *errmsg, const char *synopsis,
|
||||
const char *short_opts,
|
||||
struct option const long_opts[],
|
||||
const char * const opts_help[]);
|
||||
|
||||
/**
|
||||
* Show usage and exit
|
||||
|
@ -1 +1 @@
|
||||
#define DTC_VERSION "DTC 1.4.2-g0931cea3"
|
||||
#define DTC_VERSION "DTC 1.4.4-g756ffc4f"
|
||||
|
Loading…
Reference in New Issue
Block a user