Devicetree updates for v5.13:

- Refactoring powerpc and arm64 kexec DT handling to common code. This
   enables IMA on arm64.
 
 - Add kbuild support for applying DT overlays at build time. The first
   user are the DT unittests.
 
 - Fix kerneldoc formatting and W=1 warnings in drivers/of/
 
 - Fix handling 64-bit flag on PCI resources
 
 - Bump dtschema version required to v2021.2.1
 
 - Enable undocumented compatible checks for dtbs_check. This allows
   tracking of missing binding schemas.
 
 - DT docs improvements. Regroup the DT docs and add the example schema
   and DT kernel ABI docs to the doc build.
 
 - Convert Broadcom Bluetooth and video-mux bindings to schema
 
 - Add QCom sm8250 Venus video codec binding schema
 
 - Add vendor prefixes for AESOP, YIC System Co., Ltd, and Siliconfile
   Technologies Inc.
 
 - Cleanup of DT schema type references on common properties and
   standard unit properties
 -----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCgAuFiEEktVUI4SxYhzZyEuo+vtdtY28YcMFAmCIYdgQHHJvYmhAa2Vy
 bmVsLm9yZwAKCRD6+121jbxhw/PKEACkOCWDnLSY9U7w1uGDHr6UgXIWOY9j8bYy
 2pTvDrVa6KZphT6yGU/hxrOk8Mqh5AMd2vUhO2OCoyyl/priTv+Ktqo+bikvJZLa
 MQm3JnrLpPy/GetdmVD8wq1l+FoeOSTnRIJqRxInsd8UFVpZImtP22ELox6KgGiv
 keVHIrjsHU/HpafK3w8wHCLikCZk+1Gl6pL/QgFDv2FaaCTKW16Dt64dPqYm49Xk
 j7YMMQWl+3NJ9ywZV0+PMbl9udi3EjGm5Ap5VfKzpj53Nh07QObg/QtH/1sj0HPo
 apyW7jAyQFyLytbjxzFL/tljtOeW/5rZos1GWThZ326e+Y0mTKUTDZShvNplfjIf
 e26FvVi7gndWlRSr30Ia5gdNFAx72IkpJUAuypBXgb+qNPchBJjAXLn9tcIcg/k+
 2R6BIB7SkVLpgTnJ1Bq1+PRqkKM+ggACdJNJIUApj44xoiG01vtGDGRaFuIio+Ch
 HT4aBbic4kLvagm8VzuiIF/sL7af5pntzArcyOfQTaZ92DyGI2C0j90rK3yPRIYM
 u9qX/24t1SXiUji74QpoQFzt/+Egy5hYXMJOJJSywUjKf7DBhehqklTjiJRQHKm6
 0DJ/n8q4lNru8F0Y4keKSuYTfHBstF7fS3UTH/rUmBAbfEwkvZe6B29KQbs+7aph
 GTw+jeoR5Q==
 =rF27
 -----END PGP SIGNATURE-----

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

Pull devicetree updates from Rob Herring:

 - Refactor powerpc and arm64 kexec DT handling to common code. This
   enables IMA on arm64.

 - Add kbuild support for applying DT overlays at build time. The first
   user are the DT unittests.

 - Fix kerneldoc formatting and W=1 warnings in drivers/of/

 - Fix handling 64-bit flag on PCI resources

 - Bump dtschema version required to v2021.2.1

 - Enable undocumented compatible checks for dtbs_check. This allows
   tracking of missing binding schemas.

 - DT docs improvements. Regroup the DT docs and add the example schema
   and DT kernel ABI docs to the doc build.

 - Convert Broadcom Bluetooth and video-mux bindings to schema

 - Add QCom sm8250 Venus video codec binding schema

 - Add vendor prefixes for AESOP, YIC System Co., Ltd, and Siliconfile
   Technologies Inc.

 - Cleanup of DT schema type references on common properties and
   standard unit properties

* tag 'devicetree-for-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (64 commits)
  powerpc: If kexec_build_elf_info() fails return immediately from elf64_load()
  powerpc: Free fdt on error in elf64_load()
  of: overlay: Fix kerneldoc warning in of_overlay_remove()
  of: linux/of.h: fix kernel-doc warnings
  of/pci: Add IORESOURCE_MEM_64 to resource flags for 64-bit memory addresses
  dt-bindings: bcm4329-fmac: add optional brcm,ccode-map
  docs: dt: update writing-schema.rst references
  dt-bindings: media: venus: Add sm8250 dt schema
  of: base: Fix spelling issue with function param 'prop'
  docs: dt: Add DT API documentation
  of: Add missing 'Return' section in kerneldoc comments
  of: Fix kerneldoc output formatting
  docs: dt: Group DT docs into relevant sub-sections
  docs: dt: Make 'Devicetree' wording more consistent
  docs: dt: writing-schema: Include the example schema in the doc build
  docs: dt: writing-schema: Remove spurious indentation
  dt-bindings: Fix reference in submitting-patches.rst to the DT ABI doc
  dt-bindings: ddr: Add optional manufacturer and revision ID to LPDDR3
  dt-bindings: media: video-interfaces: Drop the example
  devicetree: bindings: clock: Minor typo fix in the file armada3700-tbg-clock.txt
  ...
This commit is contained in:
Linus Torvalds 2021-04-28 15:50:24 -07:00
commit 0080665fbd
102 changed files with 1665 additions and 1451 deletions

View File

@ -5,7 +5,7 @@ DT_MK_SCHEMA ?= dt-mk-schema
DT_SCHEMA_LINT = $(shell which yamllint)
DT_SCHEMA_MIN_VERSION = 2020.8.1
DT_SCHEMA_MIN_VERSION = 2021.2.1
PHONY += check_dtschema_version
check_dtschema_version:
@ -55,6 +55,9 @@ override DTC_FLAGS := \
-Wno-graph_child_address \
-Wno-interrupt_provider
# Disable undocumented compatible checks until warning free
override DT_CHECKER_FLAGS ?=
$(obj)/processed-schema-examples.json: $(DT_DOCS) $(src)/.yamllint check_dtschema_version FORCE
$(call if_changed_rule,chkdt)

View File

@ -26,10 +26,7 @@ properties:
- const: simple-mfd
mboxes:
$ref: '/schemas/types.yaml#/definitions/phandle'
description: |
Phandle to the firmware device's Mailbox.
(See: ../mailbox/mailbox.txt for more information)
maxItems: 1
clocks:
type: object

View File

@ -258,13 +258,11 @@ properties:
where voltage is in V, frequency is in MHz.
power-domains:
$ref: '/schemas/types.yaml#/definitions/phandle-array'
description:
List of phandles and PM domain specifiers, as defined by bindings of the
PM domain provider (see also ../power_domain.txt).
power-domain-names:
$ref: '/schemas/types.yaml#/definitions/string-array'
description:
A list of power domain name strings sorted in the same order as the
power-domains property.

View File

@ -44,7 +44,7 @@ examples:
- |
clk@1c20000 {
#clock-cells = <0>;
compatible = "allwinner,sun4i-a10-pll1";
compatible = "allwinner,sun4i-a10-pll1-clk";
reg = <0x01c20000 0x4>;
clocks = <&osc24M>;
clock-output-names = "osc24M";

View File

@ -1,6 +1,6 @@
* Time Base Generator Clock bindings for Marvell Armada 37xx SoCs
Marvell Armada 37xx SoCs provde Time Base Generator clocks which are
Marvell Armada 37xx SoCs provide Time Base Generator clocks which are
used as parent clocks for the peripheral clocks.
The TBG clock consumer should specify the desired clock by having the

View File

@ -18,10 +18,12 @@ description: |
properties:
compatible:
oneOf:
- items:
- enum:
- socionext,milbeaut-m10v-ccu
enum:
- socionext,milbeaut-m10v-ccu
reg:
maxItems: 1
clocks:
maxItems: 1
description: external clock
@ -41,7 +43,7 @@ examples:
# Clock controller node:
- |
m10v-clk-ctrl@1d021000 {
compatible = "socionext,milbeaut-m10v-clk-ccu";
compatible = "socionext,milbeaut-m10v-ccu";
reg = <0x1d021000 0x4000>;
#clock-cells = <1>;
clocks = <&clki40mhz>;

View File

@ -12,6 +12,9 @@ Required properties:
Optional properties:
- manufacturer-id : <u32> Manufacturer ID value read from Mode Register 5
- revision-id : <u32 u32> Revision IDs read from Mode Registers 6 and 7
The following optional properties represent the minimum value of some AC
timing parameters of the DDR device in terms of number of clock cycles.
These values shall be obtained from the device data-sheet.
@ -49,6 +52,8 @@ samsung_K3QF2F20DB: lpddr3 {
compatible = "samsung,K3QF2F20DB", "jedec,lpddr3";
density = <16384>;
io-width = <32>;
manufacturer-id = <1>;
revision-id = <123 234>;
#address-cells = <1>;
#size-cells = <0>;

View File

@ -73,7 +73,6 @@ properties:
clock-output-names:
description:
Name of the LCD pixel clock created.
$ref: /schemas/types.yaml#/definitions/string-array
maxItems: 1
dmas:

View File

@ -77,12 +77,6 @@ examples:
clock-output-names = "dsi1_byte", "dsi1_ddr2", "dsi1_ddr";
pitouchscreen: panel@0 {
compatible = "raspberrypi,touchscreen";
reg = <0>;
/* ... */
};
};
...

View File

@ -2,14 +2,14 @@ Qualcomm Technologies, Inc. DPU KMS
Description:
Device tree bindings for MSM Mobile Display Subsytem(MDSS) that encapsulates
Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
sub-blocks like DPU display controller, DSI and DP interfaces etc.
The DPU display controller is found in SDM845 SoC.
MDSS:
Required properties:
- compatible: "qcom,sdm845-mdss", "qcom,sc7180-mdss"
- reg: physical base address and length of contoller's registers.
- reg: physical base address and length of controller's registers.
- reg-names: register region names. The following region is required:
* "mdss"
- power-domains: a power domain consumer specifier according to

View File

@ -40,7 +40,7 @@ additionalProperties: false
examples:
- |
panel {
compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
compatible = "startek,startek-kd050c", "panel-dpi";
label = "osddisplay";
power-supply = <&vcc_supply>;
backlight = <&backlight>;

View File

@ -64,7 +64,7 @@ examples:
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/dma/qcom-gpi.h>
gpi_dma0: dma-controller@800000 {
compatible = "qcom,gpi-dma";
compatible = "qcom,sdm845-gpi-dma";
#dma-cells = <3>;
reg = <0x00800000 0x60000>;
iommus = <&apps_smmu 0x0016 0x0>;

View File

@ -43,8 +43,7 @@ properties:
gpio-ranges: true
gpio-ranges-group-names:
$ref: /schemas/types.yaml#/definitions/string-array
gpio-ranges-group-names: true
socionext,interrupt-ranges:
description: |

View File

@ -4,7 +4,7 @@
$id: "http://devicetree.org/schemas/i2c/xlnx,xps-iic-2.00.a.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: ilinx IIC controller Device Tree Bindings
title: Xilinx IIC controller Device Tree Bindings
maintainers:
- info@mocean-labs.com

View File

@ -157,9 +157,10 @@ examples:
i2c-scl-hz = <100000>;
/* I2C device. */
nunchuk: nunchuk@52 {
compatible = "nintendo,nunchuk";
reg = <0x52 0x0 0x10>;
eeprom@57 {
compatible = "atmel,24c01";
reg = <0x57 0x0 0x10>;
pagesize = <0x8>;
};
/* I3C device with a static I2C address. */

View File

@ -53,11 +53,6 @@ examples:
#address-cells = <1>;
#size-cells = <1>;
ts_adc_syscon: ts_adc_syscon@180a6000 {
compatible = "brcm,iproc-ts-adc-syscon","syscon";
reg = <0x180a6000 0xc30>;
};
adc {
compatible = "brcm,iproc-static-adc";
adc-syscon = <&ts_adc_syscon>;

View File

@ -83,7 +83,7 @@ examples:
#size-cells = <0>;
gyroscope@0 {
compatible = "nxp,fxas2102c";
compatible = "nxp,fxas21002c";
reg = <0x0>;
spi-max-frequency = <2000000>;

View File

@ -48,7 +48,6 @@ properties:
vdd-supply: true
capella,aset-resistance-ohms:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [50000, 100000, 300000, 600000]
description: >
Sensitivity calibration resistance. Note that calibration curves

View File

@ -11,12 +11,12 @@ maintainers:
properties:
compatible:
const: upisemi,asd5182
const: upisemi,usd5182
reg:
maxItems: 1
upsemi,glass-coef:
upisemi,glass-coef:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
glass attenuation factor - compensation factor of resolution 1000

View File

@ -1,12 +1,9 @@
.. SPDX-License-Identifier: GPL-2.0
===========
Device Tree
===========
.. toctree::
:maxdepth: 1
ABI
submitting-patches
writing-bindings
writing-schema
submitting-patches

View File

@ -32,6 +32,5 @@ properties:
Duration in seconds which the key should be kept pressed for device to
power off automatically. Device with key pressed shutdown feature can
specify this property.
$ref: /schemas/types.yaml#/definitions/uint32
additionalProperties: true

View File

@ -47,7 +47,7 @@ examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
htintc: interrupt-controller@1fb000080 {
compatible = "loongson,htintc-1.0";
compatible = "loongson,htpic-1.0";
reg = <0xfb000080 0x40>;
interrupt-controller;
#interrupt-cells = <1>;

View File

@ -14,6 +14,17 @@ properties:
compatible:
const: intel,lgm-ssoled
reg:
maxItems: 1
clocks:
maxItems: 2
clock-names:
items:
- const: sso
- const: fpid
gpio-controller: true
'#gpio-cells':
@ -36,8 +47,15 @@ properties:
additionalProperties: false
properties:
'#address-cells':
const: 1
'#size-cells':
const: 0
patternProperties:
"^led@[0-23]$":
"^led@[0-2]$":
type: object
properties:
@ -81,7 +99,7 @@ examples:
#include <dt-bindings/leds/common.h>
ssogpio: ssogpio@e0d40000 {
compatible = "intel,sso-led";
compatible = "intel,lgm-ssoled";
reg = <0xE0D40000 0x2E4>;
gpio-controller;
#gpio-cells = <2>;
@ -103,8 +121,8 @@ examples:
led-gpio = <&ssogpio 0 0>;
};
led@23 {
reg = <23>;
led@2 {
reg = <2>;
function = LED_FUNCTION_POWER;
color = <LED_COLOR_ID_GREEN>;
led-gpio = <&ssogpio 23 0>;

View File

@ -0,0 +1,167 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/media/qcom,sm8250-venus.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Qualcomm Venus video encode and decode accelerators
maintainers:
- Stanimir Varbanov <stanimir.varbanov@linaro.org>
description: |
The Venus IP is a video encode and decode accelerator present
on Qualcomm platforms
properties:
compatible:
const: qcom,sm8250-venus
reg:
maxItems: 1
interrupts:
maxItems: 1
power-domains:
minItems: 2
maxItems: 3
power-domain-names:
minItems: 2
maxItems: 3
items:
- const: venus
- const: vcodec0
- const: mx
clocks:
maxItems: 3
clock-names:
items:
- const: iface
- const: core
- const: vcodec0_core
iommus:
maxItems: 1
memory-region:
maxItems: 1
interconnects:
maxItems: 2
interconnect-names:
items:
- const: cpu-cfg
- const: video-mem
resets:
maxItems: 2
reset-names:
items:
- const: bus
- const: core
video-decoder:
type: object
properties:
compatible:
const: venus-decoder
required:
- compatible
additionalProperties: false
video-encoder:
type: object
properties:
compatible:
const: venus-encoder
required:
- compatible
additionalProperties: false
video-firmware:
type: object
description: |
Firmware subnode is needed when the platform does not
have TrustZone.
properties:
iommus:
maxItems: 1
required:
- iommus
required:
- compatible
- reg
- interrupts
- power-domains
- power-domain-names
- clocks
- clock-names
- interconnects
- interconnect-names
- iommus
- memory-region
- resets
- reset-names
- video-decoder
- video-encoder
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,videocc-sm8250.h>
#include <dt-bindings/interconnect/qcom,sm8250.h>
#include <dt-bindings/clock/qcom,gcc-sm8250.h>
#include <dt-bindings/power/qcom-rpmpd.h>
venus: video-codec@aa00000 {
compatible = "qcom,sm8250-venus";
reg = <0x0aa00000 0xff000>;
interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&videocc MVS0C_GDSC>,
<&videocc MVS0_GDSC>,
<&rpmhpd SM8250_MX>;
power-domain-names = "venus", "vcodec0", "mx";
clocks = <&gcc GCC_VIDEO_AXI0_CLK>,
<&videocc VIDEO_CC_MVS0C_CLK>,
<&videocc VIDEO_CC_MVS0_CLK>;
clock-names = "iface", "core", "vcodec0_core";
interconnects = <&gem_noc MASTER_AMPSS_M0 &config_noc SLAVE_VENUS_CFG>,
<&mmss_noc MASTER_VIDEO_P0 &mc_virt SLAVE_EBI_CH0>;
interconnect-names = "cpu-cfg", "video-mem";
iommus = <&apps_smmu 0x2100 0x0400>;
memory-region = <&video_mem>;
resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>,
<&videocc VIDEO_CC_MVS0C_CLK_ARES>;
reset-names = "bus", "core";
video-decoder {
compatible = "venus-decoder";
};
video-encoder {
compatible = "venus-encoder";
};
};

View File

@ -215,130 +215,3 @@ properties:
CCP2, for instance.
additionalProperties: true
examples:
# The example snippet below describes two data pipelines. ov772x and imx074
# are camera sensors with a parallel and serial (MIPI CSI-2) video bus
# respectively. Both sensors are on the I2C control bus corresponding to the
# i2c0 controller node. ov772x sensor is linked directly to the ceu0 video
# host interface. imx074 is linked to ceu0 through the MIPI CSI-2 receiver
# (csi2). ceu0 has a (single) DMA engine writing captured data to memory.
# ceu0 node has a single 'port' node which may indicate that at any time
# only one of the following data pipelines can be active:
# ov772x -> ceu0 or imx074 -> csi2 -> ceu0.
- |
ceu@fe910000 {
compatible = "renesas,sh-mobile-ceu";
reg = <0xfe910000 0xa0>;
interrupts = <0x880>;
mclk: master_clock {
compatible = "renesas,ceu-clock";
#clock-cells = <1>;
clock-frequency = <50000000>; /* Max clock frequency */
clock-output-names = "mclk";
};
port {
#address-cells = <1>;
#size-cells = <0>;
/* Parallel bus endpoint */
ceu0_1: endpoint@1 {
reg = <1>; /* Local endpoint # */
remote-endpoint = <&ov772x_1_1>; /* Remote phandle */
bus-width = <8>; /* Used data lines */
data-shift = <2>; /* Lines 9:2 are used */
/* If hsync-active/vsync-active are missing,
embedded BT.656 sync is used */
hsync-active = <0>; /* Active low */
vsync-active = <0>; /* Active low */
data-active = <1>; /* Active high */
pclk-sample = <1>; /* Rising */
};
/* MIPI CSI-2 bus endpoint */
ceu0_0: endpoint@0 {
reg = <0>;
remote-endpoint = <&csi2_2>;
};
};
};
i2c {
#address-cells = <1>;
#size-cells = <0>;
camera@21 {
compatible = "ovti,ov772x";
reg = <0x21>;
vddio-supply = <&regulator1>;
vddcore-supply = <&regulator2>;
clock-frequency = <20000000>;
clocks = <&mclk 0>;
clock-names = "xclk";
port {
/* With 1 endpoint per port no need for addresses. */
ov772x_1_1: endpoint {
bus-width = <8>;
remote-endpoint = <&ceu0_1>;
hsync-active = <1>;
vsync-active = <0>; /* Who came up with an
inverter here ?... */
data-active = <1>;
pclk-sample = <1>;
};
};
};
camera@1a {
compatible = "sony,imx074";
reg = <0x1a>;
vddio-supply = <&regulator1>;
vddcore-supply = <&regulator2>;
clock-frequency = <30000000>; /* Shared clock with ov772x_1 */
clocks = <&mclk 0>;
clock-names = "sysclk"; /* Assuming this is the
name in the datasheet */
port {
imx074_1: endpoint {
clock-lanes = <0>;
data-lanes = <1 2>;
remote-endpoint = <&csi2_1>;
};
};
};
};
csi2: csi2@ffc90000 {
compatible = "renesas,sh-mobile-csi2";
reg = <0xffc90000 0x1000>;
interrupts = <0x17a0>;
#address-cells = <1>;
#size-cells = <0>;
port@1 {
compatible = "renesas,csi2c"; /* One of CSI2I and CSI2C. */
reg = <1>; /* CSI-2 PHY #1 of 2: PHY_S,
PHY_M has port address 0,
is unused. */
csi2_1: endpoint {
clock-lanes = <0>;
data-lanes = <2 1>;
remote-endpoint = <&imx074_1>;
};
};
port@2 {
reg = <2>; /* port 2: link to the CEU */
csi2_2: endpoint {
remote-endpoint = <&ceu0_0>;
};
};
};
...

View File

@ -1,60 +0,0 @@
Video Multiplexer
=================
Video multiplexers allow to select between multiple input ports. Video received
on the active input port is passed through to the output port. Muxes described
by this binding are controlled by a multiplexer controller that is described by
the bindings in Documentation/devicetree/bindings/mux/mux-controller.txt
Required properties:
- compatible : should be "video-mux"
- mux-controls : mux controller node to use for operating the mux
- #address-cells: should be <1>
- #size-cells: should be <0>
- port@*: at least three port nodes containing endpoints connecting to the
source and sink devices according to of_graph bindings. The last port is
the output port, all others are inputs.
Optionally, #address-cells, #size-cells, and port nodes can be grouped under a
ports node as described in Documentation/devicetree/bindings/graph.txt.
Example:
mux: mux-controller {
compatible = "gpio-mux";
#mux-control-cells = <0>;
mux-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
};
video-mux {
compatible = "video-mux";
mux-controls = <&mux>;
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
mux_in0: endpoint {
remote-endpoint = <&video_source0_out>;
};
};
port@1 {
reg = <1>;
mux_in1: endpoint {
remote-endpoint = <&video_source1_out>;
};
};
port@2 {
reg = <2>;
mux_out: endpoint {
remote-endpoint = <&capture_interface_in>;
};
};
};
};

View File

@ -0,0 +1,106 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/video-mux.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Video Multiplexer
maintainers:
- Sakari Ailus <sakari.ailus@linux.intel.com>
- Laurent Pinchart <laurent.pinchart@ideasonboard.com>
description:
Video multiplexers allow to select between multiple input ports. Video
received on the active input port is passed through to the output port. Muxes
described by this binding are controlled by a multiplexer controller.
properties:
compatible:
const: video-mux
mux-controls:
maxItems: 1
'#address-cells':
const: 1
'#size-cells':
const: 0
ports:
$ref: /schemas/graph.yaml#/properties/ports
patternProperties:
'^port@':
$ref: /schemas/graph.yaml#/properties/port
required:
- port@0
- port@1
- port@2
patternProperties:
'^port@':
$ref: /schemas/graph.yaml#/properties/port
description:
At least three port nodes containing endpoints connecting to the source
and sink devices according to of_graph bindings. The last port is the
output port, all others are inputs.
required:
- compatible
- mux-controls
oneOf:
- required:
- ports
- required:
- port@0
- port@1
- port@2
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
mux: mux-controller {
compatible = "gpio-mux";
#mux-control-cells = <0>;
mux-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
};
video-mux {
compatible = "video-mux";
mux-controls = <&mux>;
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
mux_in0: endpoint {
remote-endpoint = <&video_source0_out>;
};
};
port@1 {
reg = <1>;
mux_in1: endpoint {
remote-endpoint = <&video_source1_out>;
};
};
port@2 {
reg = <2>;
mux_out: endpoint {
remote-endpoint = <&capture_interface_in>;
};
};
};
...

View File

@ -34,7 +34,7 @@ properties:
- description: EMC general interrupt
memory-region:
$ref: /schemas/types.yaml#/definitions/phandle
maxItems: 1
description:
phandle to a reserved memory region describing the table of EMC
frequencies trained by the firmware

View File

@ -57,7 +57,6 @@ properties:
- const: per
clock-frequency:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
The oscillator frequency driving the flexcan device, filled in by the
boot loader. This property should only be used the used operating system

View File

@ -0,0 +1,109 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/wireless/brcm,bcm4329-fmac.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Broadcom BCM4329 family fullmac wireless SDIO devices
maintainers:
- Arend van Spriel <arend@broadcom.com>
description:
The Broadcom Single chip MAC part for the BCM4329 family and
later Cypress chips in the same family named CYW4373 and similar.
These chips also have a Bluetooth portion described in a separate
binding.
properties:
compatible:
oneOf:
- items:
- enum:
- brcm,bcm43143-fmac
- brcm,bcm4341b0-fmac
- brcm,bcm4341b4-fmac
- brcm,bcm4341b5-fmac
- brcm,bcm4329-fmac
- brcm,bcm4330-fmac
- brcm,bcm4334-fmac
- brcm,bcm43340-fmac
- brcm,bcm4335-fmac
- brcm,bcm43362-fmac
- brcm,bcm4339-fmac
- brcm,bcm43430a0-fmac
- brcm,bcm43430a1-fmac
- brcm,bcm43455-fmac
- brcm,bcm43456-fmac
- brcm,bcm4354-fmac
- brcm,bcm4356-fmac
- brcm,bcm4359-fmac
- cypress,cyw4373-fmac
- cypress,cyw43012-fmac
- const: brcm,bcm4329-fmac
- const: brcm,bcm4329-fmac
reg:
description: SDIO function number for the device, for most cases
this will be 1.
interrupts:
maxItems: 1
description: Out-of-band (OOB) IRQ line for waking up the host
in response to WLAN activity. This corresponds to the HOST_WAKE
line into the chip.
interrupt-names:
description: Name for the OOB IRQ, this must be set to "host-wake".
const: host-wake
brcm,drive-strength:
$ref: /schemas/types.yaml#/definitions/uint32
description: Drive strength used for the SDIO pins on the device in mA.
minimum: 0
maximum: 32
reset-gpios:
maxItems: 1
description: A GPIO line connected to the WL_RST line, if present
this shall be flagged as active low.
brcm,ccode-map:
$ref: /schemas/types.yaml#/definitions/string-array
description: Multiple strings for translating ISO3166 country code to
brcmfmac firmware country code and revision.
items:
pattern: '^[A-Z][A-Z]-[A-Z][0-9A-Z]-[0-9]+$'
required:
- compatible
- reg
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/gpio/gpio.h>
mmc@80118000 {
compatible = "arm,pl18x", "arm,primecell";
reg = <0x80118000 0x1000>;
clocks = <&clk 0>, <&clk 1>;
clock-names = "mclk", "apb_pclk";
interrupts = <0 60 IRQ_TYPE_LEVEL_HIGH>;
bus-width = <4>;
non-removable;
vmmc-supply = <&wl_bt_reg>;
#address-cells = <1>;
#size-cells = <0>;
wifi@1 {
compatible = "brcm,bcm4334-fmac", "brcm,bcm4329-fmac";
reg = <1>;
interrupt-parent = <&gpio>;
interrupts = <24 IRQ_TYPE_EDGE_FALLING>;
interrupt-names = "host-wake";
reset-gpios = <&gpio 23 GPIO_ACTIVE_LOW>;
brcm,ccode-map = "JP-JP-78", "US-Q2-86";
};
};

View File

@ -1,38 +0,0 @@
Broadcom BCM43xx Fullmac wireless SDIO devices
This node provides properties for controlling the Broadcom wireless device. The
node is expected to be specified as a child node to the SDIO controller that
connects the device to the system.
Required properties:
- compatible : Should be "brcm,bcm4329-fmac".
Optional properties:
- brcm,drive-strength : drive strength used for SDIO pins on device in mA
(default = 6).
- interrupts : specifies attributes for the out-of-band interrupt (host-wake).
When not specified the device will use in-band SDIO interrupts.
- interrupt-names : name of the out-of-band interrupt, which must be set
to "host-wake".
Example:
mmc3: mmc@1c12000 {
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&mmc3_pins_a>;
vmmc-supply = <&reg_vmmc3>;
bus-width = <4>;
non-removable;
brcmf: wifi@1 {
reg = <1>;
compatible = "brcm,bcm4329-fmac";
interrupt-parent = <&pio>;
interrupts = <10 8>; /* PH10 / EINT10 */
interrupt-names = "host-wake";
};
};

View File

@ -2,7 +2,7 @@
%YAML 1.2
---
$id: http://devicetree.org/schemas/nvmem/nvmem-consumer.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
$schema: http://devicetree.org/meta-schemas/base.yaml#
title: NVMEM (Non Volatile Memory) Consumer Device Tree Bindings
@ -23,12 +23,10 @@ properties:
List of phandle to the nvmem data cells.
nvmem-names:
$ref: /schemas/types.yaml#/definitions/string-array
description:
Names for the each nvmem provider.
nvmem-cell-names:
$ref: /schemas/types.yaml#/definitions/string-array
description:
Names for each nvmem-cells specified.

View File

@ -222,7 +222,7 @@ examples:
};
serdes@5000000 {
compatible = "cdns,ti,sierra-phy-t0";
compatible = "ti,sierra-phy-t0";
reg-names = "serdes";
reg = <0x5000000 0x10000>;
#address-cells = <1>;

View File

@ -39,7 +39,6 @@ properties:
maxItems: 1
ti,watchdog-timeout-ms:
$ref: /schemas/types.yaml#/definitions/uint32
default: 0
description: |
Watchdog timer in ms. 0 (default) disables the watchdog

View File

@ -61,7 +61,7 @@ examples:
#size-cells = <0>;
cw2015@62 {
compatible = "cellwise,cw201x";
compatible = "cellwise,cw2015";
reg = <0x62>;
cellwise,battery-profile = /bits/ 8 <
0x17 0x67 0x80 0x73 0x6E 0x6C 0x6B 0x63

View File

@ -29,12 +29,10 @@ properties:
description: I2C address of the charger.
lltc,rsnsb-micro-ohms:
$ref: /schemas/types.yaml#/definitions/uint32
description: Battery sense resistor in microohm.
minimum: 1000
lltc,rsnsi-micro-ohms:
$ref: /schemas/types.yaml#/definitions/uint32
description: Input current sense resistor in microohm.
minimum: 1000

View File

@ -18,25 +18,3 @@ properties:
additionalProperties: true
examples:
- |
power {
#address-cells = <1>;
#size-cells = <0>;
usb_charger:charger@e {
compatible = "some,usb-charger";
reg = <0xe>;
};
ac_charger:charger@c {
compatible = "some,ac-charger";
reg = <0xc>;
};
battery:battery@b {
compatible = "some,battery";
reg = <0xb>;
power-supplies = <&usb_charger>, <&ac_charger>;
};
};

View File

@ -23,7 +23,6 @@ properties:
properties:
qcom,soft-start-us:
$ref: /schemas/types.yaml#/definitions/uint32
description: Regulator soft start time in microseconds.
enum: [200, 400, 600, 800]
default: 200

View File

@ -93,7 +93,7 @@ properties:
# The following are the optional properties:
memory-region:
$ref: /schemas/types.yaml#/definitions/phandle
maxItems: 1
description: |
phandle to the reserved memory node to be associated
with the remoteproc device. The reserved memory node

View File

@ -144,7 +144,7 @@ examples:
interrupts = <1>;
bluetooth {
compatible = "brcm,bcm43341-bt";
compatible = "brcm,bcm4330-bt";
interrupt-parent = <&gpio>;
interrupts = <10>;
};

View File

@ -29,11 +29,9 @@ properties:
clock-frequency:
description: common clock binding; frequency of MCKO
$ref: /schemas/types.yaml#/definitions/uint32
clock-output-names:
description: common clock name
$ref: /schemas/types.yaml#/definitions/string
required:
- compatible

View File

@ -32,7 +32,7 @@ properties:
The last one integer is the length of the shared memory.
memory-region:
$ref: '/schemas/types.yaml#/definitions/phandle'
maxItems: 1
description: |
Shared memory region to EC. A "shared-dma-pool".
See ../reserved-memory/reserved-memory.txt for details.

View File

@ -78,7 +78,6 @@ properties:
clock-frequency:
description: for audio_clkout0/1/2/3
$ref: /schemas/types.yaml#/definitions/uint32-array
clkout-lr-asynchronous:
description: audio_clkoutn is asynchronizes with lr-clock.

View File

@ -90,8 +90,8 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
ethernet-switch@0 {
compatible = "micrel,ks8995m";
display@0 {
compatible = "lg,lg4573";
spi-max-frequency = <1000000>;
reg = <0>;
};

View File

@ -181,22 +181,23 @@ additionalProperties: true
examples:
- |
spi@f00 {
spi@80010000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
reg = <0xf00 0x20>;
interrupts = <2 13 0 2 14 0>;
interrupt-parent = <&mpc5200_pic>;
compatible = "fsl,imx28-spi";
reg = <0x80010000 0x2000>;
interrupts = <96>;
dmas = <&dma_apbh 0>;
dma-names = "rx-tx";
ethernet-switch@0 {
compatible = "micrel,ks8995m";
display@0 {
compatible = "lg,lg4573";
spi-max-frequency = <1000000>;
reg = <0>;
};
codec@1 {
compatible = "ti,tlv320aic26";
sensor@1 {
compatible = "bosch,bme680";
spi-max-frequency = <100000>;
reg = <1>;
};

View File

@ -75,16 +75,12 @@ examples:
spi-flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <40000000>;
};
spi-device@1 {
compatible = "lineartechnology,ltc2488";
sensor@1 {
compatible = "bosch,bme680";
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <10000000>;
};
};

View File

@ -96,12 +96,6 @@ examples:
dma-names = "rx", "tx";
cs-gpios = <&gpioa 11 0>;
aardvark@0 {
compatible = "totalphase,aardvark";
reg = <0>;
spi-max-frequency = <4000000>;
st,spi-midi-ns = <4000>;
};
};
...

View File

@ -1,7 +1,7 @@
.. SPDX-License-Identifier: GPL-2.0
==========================================
Submitting devicetree (DT) binding patches
Submitting Devicetree (DT) binding patches
==========================================
I. For patch submitters
@ -25,7 +25,7 @@ I. For patch submitters
make dt_binding_check
See Documentation/devicetree/writing-schema.rst for more details about
See Documentation/devicetree/bindings/writing-schema.rst for more details about
schema and tools setup.
3) DT binding files should be dual licensed. The preferred license tag is
@ -84,7 +84,7 @@ II. For kernel maintainers
III. Notes
==========
0) Please see ...bindings/ABI.txt for details regarding devicetree ABI.
0) Please see :doc:`ABI` for details regarding devicetree ABI.
1) This document is intended as a general familiarization with the process as
decided at the 2013 Kernel Summit. When in doubt, the current word of the

View File

@ -59,7 +59,6 @@ patternProperties:
properties:
reg:
$ref: /schemas/types.yaml#/definitions/uint32
description: Specify the sensor channel. There are 8 channels in PMIC5's ADC TM
minimum: 0
maximum: 7
@ -78,7 +77,6 @@ patternProperties:
also known as absolute calibration.
qcom,hw-settle-time-us:
$ref: /schemas/types.yaml#/definitions/uint32
description: Time between AMUX getting configured and the ADC starting conversion.
enum: [15, 100, 200, 300, 400, 500, 600, 700, 1000, 2000, 4000, 8000, 16000, 32000, 64000, 128000]

View File

@ -23,6 +23,9 @@ properties:
maxItems: 1
interrupts:
maxItems: 1
spi-max-frequency: true
compatible:
items:
- enum:

View File

@ -16,7 +16,6 @@ properties:
pattern: "^usb(@.*)?"
phys:
$ref: /schemas/types.yaml#/definitions/phandle-array
description:
List of all the USB PHYs on this HCD

View File

@ -57,6 +57,8 @@ patternProperties:
description: Advantech Corporation
"^aeroflexgaisler,.*":
description: Aeroflex Gaisler AB
"^aesop,.*":
description: AESOP Embedded Forum
"^al,.*":
description: Annapurna Labs
"^alcatel,.*":
@ -1030,6 +1032,8 @@ patternProperties:
description: Silergy Corp.
"^silex-insight,.*":
description: Silex Insight
"^siliconfile,.*":
description: Siliconfile Technologies lnc.
"^siliconmitus,.*":
description: Silicon Mitus, Inc.
"^siemens,.*":
@ -1282,6 +1286,8 @@ patternProperties:
description: Yamaha Corporation
"^yes-optoelectronics,.*":
description: Yes Optoelectronics Co.,Ltd.
"^yic,.*":
description: YIC System Co., Ltd.
"^ylm,.*":
description: Shenzhen Yangliming Electronic Technology Co., Ltd.
"^yna,.*":

View File

@ -1,6 +1,6 @@
.. SPDX-License-Identifier: GPL-2.0
Writing DeviceTree Bindings in json-schema
Writing Devicetree Bindings in json-schema
==========================================
Devicetree bindings are written using json-schema vocabulary. Schema files are
@ -8,6 +8,8 @@ written in a JSON compatible subset of YAML. YAML is used instead of JSON as it
is considered more human readable and has some advantages such as allowing
comments (Prefixed with '#').
Also see :ref:`example-schema`.
Schema Contents
---------------
@ -46,12 +48,12 @@ select
schema. By default without 'select', nodes are matched against their possible
compatible string values or node name. Most bindings should not need select.
allOf
allOf
Optional. A list of other schemas to include. This is used to
include other schemas the binding conforms to. This may be schemas for a
particular class of devices such as I2C or SPI controllers.
properties
properties
A set of sub-schema defining all the DT properties for the
binding. The exact schema syntax depends on whether properties are known,
common properties (e.g. 'interrupts') or are binding/vendor specific properties.
@ -170,3 +172,12 @@ json-schema Resources
`JSON-Schema Specifications <http://json-schema.org/>`_
`Using JSON Schema Book <http://usingjsonschema.com/>`_
.. _example-schema:
Annotated Example Schema
------------------------
Also available as a separate file: :download:`example-schema.yaml`
.. literalinclude:: example-schema.yaml

View File

@ -1,10 +1,10 @@
.. SPDX-License-Identifier: GPL-2.0
=============
DT Changesets
=============
=====================
Devicetree Changesets
=====================
A DT changeset is a method which allows one to apply changes
A Devicetree changeset is a method which allows one to apply changes
in the live tree in such a way that either the full set of changes
will be applied, or none of them will be. If an error occurs partway
through applying the changeset, then the tree will be rolled back to the

View File

@ -1,11 +1,11 @@
.. SPDX-License-Identifier: GPL-2.0
==================================
Device Tree Dynamic Resolver Notes
==================================
=================================
Devicetree Dynamic Resolver Notes
=================================
This document describes the implementation of the in-kernel
Device Tree resolver, residing in drivers/of/resolver.c
DeviceTree resolver, residing in drivers/of/resolver.c
How the resolver works
----------------------

View File

@ -1,17 +1,30 @@
.. SPDX-License-Identifier: GPL-2.0
=============================
Open Firmware and Device Tree
Open Firmware and Devicetree
=============================
Kernel Devicetree Usage
=======================
.. toctree::
:maxdepth: 1
usage-model
writing-schema
of_unittest
kernel-api
Devicetree Overlays
===================
.. toctree::
:maxdepth: 1
changesets
dynamic-resolution-notes
of_unittest
overlay-notes
Devicetree Bindings
===================
.. toctree::
:maxdepth: 1
bindings/index

View File

@ -0,0 +1,57 @@
.. SPDX-License-Identifier: GPL-2.0
.. _devicetree:
======================================
DeviceTree Kernel API
======================================
Core functions
--------------
.. kernel-doc:: drivers/of/base.c
:export:
.. kernel-doc:: include/linux/of.h
:internal:
.. kernel-doc:: drivers/of/property.c
:export:
.. kernel-doc:: include/linux/of_graph.h
:internal:
.. kernel-doc:: drivers/of/address.c
:export:
.. kernel-doc:: drivers/of/irq.c
:export:
.. kernel-doc:: drivers/of/fdt.c
:export:
Driver model functions
----------------------
.. kernel-doc:: include/linux/of_device.h
:internal:
.. kernel-doc:: drivers/of/device.c
:export:
.. kernel-doc:: include/linux/of_platform.h
:internal:
.. kernel-doc:: drivers/of/platform.c
:export:
Overlay and Dynamic DT functions
--------------------------------
.. kernel-doc:: drivers/of/resolver.c
:export:
.. kernel-doc:: drivers/of/dynamic.c
:export:
.. kernel-doc:: drivers/of/overlay.c
:export:

View File

@ -1,8 +1,8 @@
.. SPDX-License-Identifier: GPL-2.0
==================================
Open Firmware Device Tree Unittest
==================================
=================================
Open Firmware Devicetree Unittest
=================================
Author: Gaurav Minocha <gaurav.minocha.os@gmail.com>

View File

@ -1,8 +1,8 @@
.. SPDX-License-Identifier: GPL-2.0
=========================
Device Tree Overlay Notes
=========================
========================
Devicetree Overlay Notes
========================
This document describes the implementation of the in-kernel
device tree overlay functionality residing in drivers/of/overlay.c and is a
@ -11,7 +11,7 @@ companion document to Documentation/devicetree/dynamic-resolution-notes.rst[1]
How overlays work
-----------------
A Device Tree's overlay purpose is to modify the kernel's live tree, and
A Devicetree's overlay purpose is to modify the kernel's live tree, and
have the modification affecting the state of the kernel in a way that
is reflecting the changes.
Since the kernel mainly deals with devices, any new device node that result

View File

@ -1,8 +1,8 @@
.. SPDX-License-Identifier: GPL-2.0
=========================
Linux and the Device Tree
=========================
========================
Linux and the Devicetree
========================
The Linux usage model for device tree data
@ -14,7 +14,7 @@ at devicetree.org\ [1]_.
.. [1] https://www.devicetree.org/specifications/
The "Open Firmware Device Tree", or simply Device Tree (DT), is a data
The "Open Firmware Device Tree", or simply Devicetree (DT), is a data
structure and language for describing hardware. More specifically, it
is a description of hardware that is readable by an operating system
so that the operating system doesn't need to hard code details of the

View File

@ -1113,6 +1113,7 @@ config KEXEC
config KEXEC_FILE
bool "kexec file based system call"
select KEXEC_CORE
select HAVE_IMA_KEXEC if IMA
help
This is new version of kexec system call. This system call is
file based and takes file descriptors as system call argument

View File

@ -96,10 +96,6 @@ struct kimage_arch {
void *dtb;
phys_addr_t dtb_mem;
phys_addr_t kern_reloc;
/* Core ELF header buffer */
void *elf_headers;
unsigned long elf_headers_mem;
unsigned long elf_headers_sz;
};
#ifdef CONFIG_KEXEC_FILE

View File

@ -15,23 +15,12 @@
#include <linux/kexec.h>
#include <linux/libfdt.h>
#include <linux/memblock.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/vmalloc.h>
#include <asm/byteorder.h>
/* relevant device tree properties */
#define FDT_PROP_KEXEC_ELFHDR "linux,elfcorehdr"
#define FDT_PROP_MEM_RANGE "linux,usable-memory-range"
#define FDT_PROP_INITRD_START "linux,initrd-start"
#define FDT_PROP_INITRD_END "linux,initrd-end"
#define FDT_PROP_BOOTARGS "bootargs"
#define FDT_PROP_KASLR_SEED "kaslr-seed"
#define FDT_PROP_RNG_SEED "rng-seed"
#define RNG_SEED_SIZE 128
const struct kexec_file_ops * const kexec_file_loaders[] = {
&kexec_image_ops,
@ -40,174 +29,16 @@ const struct kexec_file_ops * const kexec_file_loaders[] = {
int arch_kimage_file_post_load_cleanup(struct kimage *image)
{
vfree(image->arch.dtb);
kvfree(image->arch.dtb);
image->arch.dtb = NULL;
vfree(image->arch.elf_headers);
image->arch.elf_headers = NULL;
image->arch.elf_headers_sz = 0;
vfree(image->elf_headers);
image->elf_headers = NULL;
image->elf_headers_sz = 0;
return kexec_image_post_load_cleanup_default(image);
}
static int setup_dtb(struct kimage *image,
unsigned long initrd_load_addr, unsigned long initrd_len,
char *cmdline, void *dtb)
{
int off, ret;
ret = fdt_path_offset(dtb, "/chosen");
if (ret < 0)
goto out;
off = ret;
ret = fdt_delprop(dtb, off, FDT_PROP_KEXEC_ELFHDR);
if (ret && ret != -FDT_ERR_NOTFOUND)
goto out;
ret = fdt_delprop(dtb, off, FDT_PROP_MEM_RANGE);
if (ret && ret != -FDT_ERR_NOTFOUND)
goto out;
if (image->type == KEXEC_TYPE_CRASH) {
/* add linux,elfcorehdr */
ret = fdt_appendprop_addrrange(dtb, 0, off,
FDT_PROP_KEXEC_ELFHDR,
image->arch.elf_headers_mem,
image->arch.elf_headers_sz);
if (ret)
return (ret == -FDT_ERR_NOSPACE ? -ENOMEM : -EINVAL);
/* add linux,usable-memory-range */
ret = fdt_appendprop_addrrange(dtb, 0, off,
FDT_PROP_MEM_RANGE,
crashk_res.start,
crashk_res.end - crashk_res.start + 1);
if (ret)
return (ret == -FDT_ERR_NOSPACE ? -ENOMEM : -EINVAL);
}
/* add bootargs */
if (cmdline) {
ret = fdt_setprop_string(dtb, off, FDT_PROP_BOOTARGS, cmdline);
if (ret)
goto out;
} else {
ret = fdt_delprop(dtb, off, FDT_PROP_BOOTARGS);
if (ret && (ret != -FDT_ERR_NOTFOUND))
goto out;
}
/* add initrd-* */
if (initrd_load_addr) {
ret = fdt_setprop_u64(dtb, off, FDT_PROP_INITRD_START,
initrd_load_addr);
if (ret)
goto out;
ret = fdt_setprop_u64(dtb, off, FDT_PROP_INITRD_END,
initrd_load_addr + initrd_len);
if (ret)
goto out;
} else {
ret = fdt_delprop(dtb, off, FDT_PROP_INITRD_START);
if (ret && (ret != -FDT_ERR_NOTFOUND))
goto out;
ret = fdt_delprop(dtb, off, FDT_PROP_INITRD_END);
if (ret && (ret != -FDT_ERR_NOTFOUND))
goto out;
}
/* add kaslr-seed */
ret = fdt_delprop(dtb, off, FDT_PROP_KASLR_SEED);
if (ret == -FDT_ERR_NOTFOUND)
ret = 0;
else if (ret)
goto out;
if (rng_is_initialized()) {
u64 seed = get_random_u64();
ret = fdt_setprop_u64(dtb, off, FDT_PROP_KASLR_SEED, seed);
if (ret)
goto out;
} else {
pr_notice("RNG is not initialised: omitting \"%s\" property\n",
FDT_PROP_KASLR_SEED);
}
/* add rng-seed */
if (rng_is_initialized()) {
void *rng_seed;
ret = fdt_setprop_placeholder(dtb, off, FDT_PROP_RNG_SEED,
RNG_SEED_SIZE, &rng_seed);
if (ret)
goto out;
get_random_bytes(rng_seed, RNG_SEED_SIZE);
} else {
pr_notice("RNG is not initialised: omitting \"%s\" property\n",
FDT_PROP_RNG_SEED);
}
out:
if (ret)
return (ret == -FDT_ERR_NOSPACE) ? -ENOMEM : -EINVAL;
return 0;
}
/*
* More space needed so that we can add initrd, bootargs, kaslr-seed,
* rng-seed, userable-memory-range and elfcorehdr.
*/
#define DTB_EXTRA_SPACE 0x1000
static int create_dtb(struct kimage *image,
unsigned long initrd_load_addr, unsigned long initrd_len,
char *cmdline, void **dtb)
{
void *buf;
size_t buf_size;
size_t cmdline_len;
int ret;
cmdline_len = cmdline ? strlen(cmdline) : 0;
buf_size = fdt_totalsize(initial_boot_params)
+ cmdline_len + DTB_EXTRA_SPACE;
for (;;) {
buf = vmalloc(buf_size);
if (!buf)
return -ENOMEM;
/* duplicate a device tree blob */
ret = fdt_open_into(initial_boot_params, buf, buf_size);
if (ret) {
vfree(buf);
return -EINVAL;
}
ret = setup_dtb(image, initrd_load_addr, initrd_len,
cmdline, buf);
if (ret) {
vfree(buf);
if (ret == -ENOMEM) {
/* unlikely, but just in case */
buf_size += DTB_EXTRA_SPACE;
continue;
} else {
return ret;
}
}
/* trim it */
fdt_pack(buf);
*dtb = buf;
return 0;
}
}
static int prepare_elf_headers(void **addr, unsigned long *sz)
{
struct crash_mem *cmem;
@ -284,12 +115,12 @@ int load_other_segments(struct kimage *image,
vfree(headers);
goto out_err;
}
image->arch.elf_headers = headers;
image->arch.elf_headers_mem = kbuf.mem;
image->arch.elf_headers_sz = headers_sz;
image->elf_headers = headers;
image->elf_load_addr = kbuf.mem;
image->elf_headers_sz = headers_sz;
pr_debug("Loaded elf core header at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
image->arch.elf_headers_mem, kbuf.bufsz, kbuf.memsz);
image->elf_load_addr, kbuf.bufsz, kbuf.memsz);
}
/* load initrd */
@ -314,12 +145,15 @@ int load_other_segments(struct kimage *image,
}
/* load dtb */
ret = create_dtb(image, initrd_load_addr, initrd_len, cmdline, &dtb);
if (ret) {
dtb = of_kexec_alloc_and_setup_fdt(image, initrd_load_addr,
initrd_len, cmdline, 0);
if (!dtb) {
pr_err("Preparing for new dtb failed\n");
goto out_err;
}
/* trim it */
fdt_pack(dtb);
dtb_len = fdt_totalsize(dtb);
kbuf.buffer = dtb;
kbuf.bufsz = dtb_len;
@ -343,6 +177,6 @@ int load_other_segments(struct kimage *image,
out_err:
image->nr_segments = orig_segments;
vfree(dtb);
kvfree(dtb);
return ret;
}

View File

@ -548,7 +548,7 @@ config KEXEC
config KEXEC_FILE
bool "kexec file based system call"
select KEXEC_CORE
select HAVE_IMA_KEXEC
select HAVE_IMA_KEXEC if IMA
select BUILD_BIN2C
select KEXEC_ELF
depends on PPC64

View File

@ -1,30 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_POWERPC_IMA_H
#define _ASM_POWERPC_IMA_H
struct kimage;
int ima_get_kexec_buffer(void **addr, size_t *size);
int ima_free_kexec_buffer(void);
#ifdef CONFIG_IMA
void remove_ima_buffer(void *fdt, int chosen_node);
#else
static inline void remove_ima_buffer(void *fdt, int chosen_node) {}
#endif
#ifdef CONFIG_IMA_KEXEC
int arch_ima_add_kexec_buffer(struct kimage *image, unsigned long load_addr,
size_t size);
int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node);
#else
static inline int setup_ima_buffer(const struct kimage *image, void *fdt,
int chosen_node)
{
remove_ima_buffer(fdt, chosen_node);
return 0;
}
#endif /* CONFIG_IMA_KEXEC */
#endif /* _ASM_POWERPC_IMA_H */

View File

@ -107,15 +107,7 @@ struct kimage_arch {
unsigned long backup_start;
void *backup_buf;
unsigned long elfcorehdr_addr;
unsigned long elf_headers_sz;
void *elf_headers;
#ifdef CONFIG_IMA_KEXEC
phys_addr_t ima_buffer_addr;
size_t ima_buffer_size;
#endif
void *fdt;
};
char *setup_kdump_cmdline(struct kimage *image, char *cmdline,
@ -123,10 +115,6 @@ char *setup_kdump_cmdline(struct kimage *image, char *cmdline,
int setup_purgatory(struct kimage *image, const void *slave_code,
const void *fdt, unsigned long kernel_load_addr,
unsigned long fdt_load_addr);
int setup_new_fdt(const struct kimage *image, void *fdt,
unsigned long initrd_load_addr, unsigned long initrd_len,
const char *cmdline);
int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size);
#ifdef CONFIG_PPC64
struct kexec_buf;
@ -136,7 +124,7 @@ int load_crashdump_segments_ppc64(struct kimage *image,
int setup_purgatory_ppc64(struct kimage *image, const void *slave_code,
const void *fdt, unsigned long kernel_load_addr,
unsigned long fdt_load_addr);
unsigned int kexec_fdt_totalsize_ppc64(struct kimage *image);
unsigned int kexec_extra_fdt_size_ppc64(struct kimage *image);
int setup_new_fdt_ppc64(const struct kimage *image, void *fdt,
unsigned long initrd_load_addr,
unsigned long initrd_len, const char *cmdline);

View File

@ -9,13 +9,6 @@ obj-$(CONFIG_PPC32) += relocate_32.o
obj-$(CONFIG_KEXEC_FILE) += file_load.o ranges.o file_load_$(BITS).o elf_$(BITS).o
ifdef CONFIG_HAVE_IMA_KEXEC
ifdef CONFIG_IMA
obj-y += ima.o
endif
endif
# Disable GCOV, KCOV & sanitizers in odd or sensitive code
GCOV_PROFILE_core_$(BITS).o := n
KCOV_INSTRUMENT_core_$(BITS).o := n

View File

@ -19,6 +19,7 @@
#include <linux/kexec.h>
#include <linux/libfdt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/slab.h>
#include <linux/types.h>
@ -29,7 +30,6 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
unsigned long cmdline_len)
{
int ret;
unsigned int fdt_size;
unsigned long kernel_load_addr;
unsigned long initrd_load_addr = 0, fdt_load_addr;
void *fdt;
@ -45,7 +45,7 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
ret = kexec_build_elf_info(kernel_buf, kernel_len, &ehdr, &elf_info);
if (ret)
goto out;
return ERR_PTR(ret);
if (image->type == KEXEC_TYPE_CRASH) {
/* min & max buffer values for kdump case */
@ -102,15 +102,10 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
pr_debug("Loaded initrd at 0x%lx\n", initrd_load_addr);
}
fdt_size = kexec_fdt_totalsize_ppc64(image);
fdt = kmalloc(fdt_size, GFP_KERNEL);
fdt = of_kexec_alloc_and_setup_fdt(image, initrd_load_addr,
initrd_len, cmdline,
kexec_extra_fdt_size_ppc64(image));
if (!fdt) {
pr_err("Not enough memory for the device tree.\n");
ret = -ENOMEM;
goto out;
}
ret = fdt_open_into(initial_boot_params, fdt, fdt_size);
if (ret < 0) {
pr_err("Error setting up the new device tree.\n");
ret = -EINVAL;
goto out;
@ -119,18 +114,22 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
ret = setup_new_fdt_ppc64(image, fdt, initrd_load_addr,
initrd_len, cmdline);
if (ret)
goto out;
goto out_free_fdt;
fdt_pack(fdt);
kbuf.buffer = fdt;
kbuf.bufsz = kbuf.memsz = fdt_size;
kbuf.bufsz = kbuf.memsz = fdt_totalsize(fdt);
kbuf.buf_align = PAGE_SIZE;
kbuf.top_down = true;
kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
ret = kexec_add_buffer(&kbuf);
if (ret)
goto out;
goto out_free_fdt;
/* FDT will be freed in arch_kimage_file_post_load_cleanup */
image->arch.fdt = fdt;
fdt_load_addr = kbuf.mem;
pr_debug("Loaded device tree at 0x%lx\n", fdt_load_addr);
@ -141,12 +140,15 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
if (ret)
pr_err("Error setting up the purgatory.\n");
goto out;
out_free_fdt:
kvfree(fdt);
out:
kfree(modified_cmdline);
kexec_free_elf_info(&elf_info);
/* Make kimage_file_post_load_cleanup free the fdt buffer for us. */
return ret ? ERR_PTR(ret) : fdt;
return ret ? ERR_PTR(ret) : NULL;
}
const struct kexec_file_ops kexec_elf64_ops = {

View File

@ -19,7 +19,6 @@
#include <linux/of_fdt.h>
#include <linux/libfdt.h>
#include <asm/setup.h>
#include <asm/ima.h>
#define SLAVE_CODE_SIZE 256 /* First 0x100 bytes */
@ -45,7 +44,7 @@ char *setup_kdump_cmdline(struct kimage *image, char *cmdline,
return NULL;
elfcorehdr_strlen = sprintf(cmdline_ptr, "elfcorehdr=0x%lx ",
image->arch.elfcorehdr_addr);
image->elf_load_addr);
if (elfcorehdr_strlen + cmdline_len > COMMAND_LINE_SIZE) {
pr_err("Appending elfcorehdr=<addr> exceeds cmdline size\n");
@ -108,183 +107,3 @@ int setup_purgatory(struct kimage *image, const void *slave_code,
return 0;
}
/**
* delete_fdt_mem_rsv - delete memory reservation with given address and size
*
* Return: 0 on success, or negative errno on error.
*/
int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size)
{
int i, ret, num_rsvs = fdt_num_mem_rsv(fdt);
for (i = 0; i < num_rsvs; i++) {
uint64_t rsv_start, rsv_size;
ret = fdt_get_mem_rsv(fdt, i, &rsv_start, &rsv_size);
if (ret) {
pr_err("Malformed device tree.\n");
return -EINVAL;
}
if (rsv_start == start && rsv_size == size) {
ret = fdt_del_mem_rsv(fdt, i);
if (ret) {
pr_err("Error deleting device tree reservation.\n");
return -EINVAL;
}
return 0;
}
}
return -ENOENT;
}
/*
* setup_new_fdt - modify /chosen and memory reservation for the next kernel
* @image: kexec image being loaded.
* @fdt: Flattened device tree for the next kernel.
* @initrd_load_addr: Address where the next initrd will be loaded.
* @initrd_len: Size of the next initrd, or 0 if there will be none.
* @cmdline: Command line for the next kernel, or NULL if there will
* be none.
*
* Return: 0 on success, or negative errno on error.
*/
int setup_new_fdt(const struct kimage *image, void *fdt,
unsigned long initrd_load_addr, unsigned long initrd_len,
const char *cmdline)
{
int ret, chosen_node;
const void *prop;
/* Remove memory reservation for the current device tree. */
ret = delete_fdt_mem_rsv(fdt, __pa(initial_boot_params),
fdt_totalsize(initial_boot_params));
if (ret == 0)
pr_debug("Removed old device tree reservation.\n");
else if (ret != -ENOENT)
return ret;
chosen_node = fdt_path_offset(fdt, "/chosen");
if (chosen_node == -FDT_ERR_NOTFOUND) {
chosen_node = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
"chosen");
if (chosen_node < 0) {
pr_err("Error creating /chosen.\n");
return -EINVAL;
}
} else if (chosen_node < 0) {
pr_err("Malformed device tree: error reading /chosen.\n");
return -EINVAL;
}
/* Did we boot using an initrd? */
prop = fdt_getprop(fdt, chosen_node, "linux,initrd-start", NULL);
if (prop) {
uint64_t tmp_start, tmp_end, tmp_size;
tmp_start = fdt64_to_cpu(*((const fdt64_t *) prop));
prop = fdt_getprop(fdt, chosen_node, "linux,initrd-end", NULL);
if (!prop) {
pr_err("Malformed device tree.\n");
return -EINVAL;
}
tmp_end = fdt64_to_cpu(*((const fdt64_t *) prop));
/*
* kexec reserves exact initrd size, while firmware may
* reserve a multiple of PAGE_SIZE, so check for both.
*/
tmp_size = tmp_end - tmp_start;
ret = delete_fdt_mem_rsv(fdt, tmp_start, tmp_size);
if (ret == -ENOENT)
ret = delete_fdt_mem_rsv(fdt, tmp_start,
round_up(tmp_size, PAGE_SIZE));
if (ret == 0)
pr_debug("Removed old initrd reservation.\n");
else if (ret != -ENOENT)
return ret;
/* If there's no new initrd, delete the old initrd's info. */
if (initrd_len == 0) {
ret = fdt_delprop(fdt, chosen_node,
"linux,initrd-start");
if (ret) {
pr_err("Error deleting linux,initrd-start.\n");
return -EINVAL;
}
ret = fdt_delprop(fdt, chosen_node, "linux,initrd-end");
if (ret) {
pr_err("Error deleting linux,initrd-end.\n");
return -EINVAL;
}
}
}
if (initrd_len) {
ret = fdt_setprop_u64(fdt, chosen_node,
"linux,initrd-start",
initrd_load_addr);
if (ret < 0)
goto err;
/* initrd-end is the first address after the initrd image. */
ret = fdt_setprop_u64(fdt, chosen_node, "linux,initrd-end",
initrd_load_addr + initrd_len);
if (ret < 0)
goto err;
ret = fdt_add_mem_rsv(fdt, initrd_load_addr, initrd_len);
if (ret) {
pr_err("Error reserving initrd memory: %s\n",
fdt_strerror(ret));
return -EINVAL;
}
}
if (cmdline != NULL) {
ret = fdt_setprop_string(fdt, chosen_node, "bootargs", cmdline);
if (ret < 0)
goto err;
} else {
ret = fdt_delprop(fdt, chosen_node, "bootargs");
if (ret && ret != -FDT_ERR_NOTFOUND) {
pr_err("Error deleting bootargs.\n");
return -EINVAL;
}
}
if (image->type == KEXEC_TYPE_CRASH) {
/*
* Avoid elfcorehdr from being stomped on in kdump kernel by
* setting up memory reserve map.
*/
ret = fdt_add_mem_rsv(fdt, image->arch.elfcorehdr_addr,
image->arch.elf_headers_sz);
if (ret) {
pr_err("Error reserving elfcorehdr memory: %s\n",
fdt_strerror(ret));
goto err;
}
}
ret = setup_ima_buffer(image, fdt, chosen_node);
if (ret) {
pr_err("Error setting up the new device tree.\n");
return ret;
}
ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0);
if (ret)
goto err;
return 0;
err:
pr_err("Error setting up the new device tree.\n");
return -EINVAL;
}

View File

@ -816,9 +816,9 @@ static int load_elfcorehdr_segment(struct kimage *image, struct kexec_buf *kbuf)
goto out;
}
image->arch.elfcorehdr_addr = kbuf->mem;
image->arch.elf_headers_sz = headers_sz;
image->arch.elf_headers = headers;
image->elf_load_addr = kbuf->mem;
image->elf_headers_sz = headers_sz;
image->elf_headers = headers;
out:
kfree(cmem);
return ret;
@ -852,7 +852,7 @@ int load_crashdump_segments_ppc64(struct kimage *image,
return ret;
}
pr_debug("Loaded elf core header at 0x%lx, bufsz=0x%lx memsz=0x%lx\n",
image->arch.elfcorehdr_addr, kbuf->bufsz, kbuf->memsz);
image->elf_load_addr, kbuf->bufsz, kbuf->memsz);
return 0;
}
@ -927,37 +927,27 @@ out:
}
/**
* kexec_fdt_totalsize_ppc64 - Return the estimated size needed to setup FDT
* for kexec/kdump kernel.
* @image: kexec image being loaded.
* kexec_extra_fdt_size_ppc64 - Return the estimated additional size needed to
* setup FDT for kexec/kdump kernel.
* @image: kexec image being loaded.
*
* Returns the estimated size needed for kexec/kdump kernel FDT.
* Returns the estimated extra size needed for kexec/kdump kernel FDT.
*/
unsigned int kexec_fdt_totalsize_ppc64(struct kimage *image)
unsigned int kexec_extra_fdt_size_ppc64(struct kimage *image)
{
unsigned int fdt_size;
u64 usm_entries;
/*
* The below estimate more than accounts for a typical kexec case where
* the additional space is to accommodate things like kexec cmdline,
* chosen node with properties for initrd start & end addresses and
* a property to indicate kexec boot..
*/
fdt_size = fdt_totalsize(initial_boot_params) + (2 * COMMAND_LINE_SIZE);
if (image->type != KEXEC_TYPE_CRASH)
return fdt_size;
return 0;
/*
* For kdump kernel, also account for linux,usable-memory and
* For kdump kernel, account for linux,usable-memory and
* linux,drconf-usable-memory properties. Get an approximate on the
* number of usable memory entries and use for FDT size estimation.
*/
usm_entries = ((memblock_end_of_DRAM() / drmem_lmb_size()) +
(2 * (resource_size(&crashk_res) / drmem_lmb_size())));
fdt_size += (unsigned int)(usm_entries * sizeof(u64));
return fdt_size;
return (unsigned int)(usm_entries * sizeof(u64));
}
/**
@ -979,10 +969,6 @@ int setup_new_fdt_ppc64(const struct kimage *image, void *fdt,
struct crash_mem *umem = NULL, *rmem = NULL;
int i, nr_ranges, ret;
ret = setup_new_fdt(image, fdt, initrd_load_addr, initrd_len, cmdline);
if (ret)
goto out;
/*
* Restrict memory usage for kdump kernel by setting up
* usable memory ranges and memory reserve map.
@ -1142,9 +1128,12 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
vfree(image->arch.backup_buf);
image->arch.backup_buf = NULL;
vfree(image->arch.elf_headers);
image->arch.elf_headers = NULL;
image->arch.elf_headers_sz = 0;
vfree(image->elf_headers);
image->elf_headers = NULL;
image->elf_headers_sz = 0;
kvfree(image->arch.fdt);
image->arch.fdt = NULL;
return kexec_image_post_load_cleanup_default(image);
}

View File

@ -1,219 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2016 IBM Corporation
*
* Authors:
* Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
*/
#include <linux/slab.h>
#include <linux/kexec.h>
#include <linux/of.h>
#include <linux/memblock.h>
#include <linux/libfdt.h>
static int get_addr_size_cells(int *addr_cells, int *size_cells)
{
struct device_node *root;
root = of_find_node_by_path("/");
if (!root)
return -EINVAL;
*addr_cells = of_n_addr_cells(root);
*size_cells = of_n_size_cells(root);
of_node_put(root);
return 0;
}
static int do_get_kexec_buffer(const void *prop, int len, unsigned long *addr,
size_t *size)
{
int ret, addr_cells, size_cells;
ret = get_addr_size_cells(&addr_cells, &size_cells);
if (ret)
return ret;
if (len < 4 * (addr_cells + size_cells))
return -ENOENT;
*addr = of_read_number(prop, addr_cells);
*size = of_read_number(prop + 4 * addr_cells, size_cells);
return 0;
}
/**
* ima_get_kexec_buffer - get IMA buffer from the previous kernel
* @addr: On successful return, set to point to the buffer contents.
* @size: On successful return, set to the buffer size.
*
* Return: 0 on success, negative errno on error.
*/
int ima_get_kexec_buffer(void **addr, size_t *size)
{
int ret, len;
unsigned long tmp_addr;
size_t tmp_size;
const void *prop;
prop = of_get_property(of_chosen, "linux,ima-kexec-buffer", &len);
if (!prop)
return -ENOENT;
ret = do_get_kexec_buffer(prop, len, &tmp_addr, &tmp_size);
if (ret)
return ret;
*addr = __va(tmp_addr);
*size = tmp_size;
return 0;
}
/**
* ima_free_kexec_buffer - free memory used by the IMA buffer
*/
int ima_free_kexec_buffer(void)
{
int ret;
unsigned long addr;
size_t size;
struct property *prop;
prop = of_find_property(of_chosen, "linux,ima-kexec-buffer", NULL);
if (!prop)
return -ENOENT;
ret = do_get_kexec_buffer(prop->value, prop->length, &addr, &size);
if (ret)
return ret;
ret = of_remove_property(of_chosen, prop);
if (ret)
return ret;
return memblock_free(addr, size);
}
/**
* remove_ima_buffer - remove the IMA buffer property and reservation from @fdt
*
* The IMA measurement buffer is of no use to a subsequent kernel, so we always
* remove it from the device tree.
*/
void remove_ima_buffer(void *fdt, int chosen_node)
{
int ret, len;
unsigned long addr;
size_t size;
const void *prop;
prop = fdt_getprop(fdt, chosen_node, "linux,ima-kexec-buffer", &len);
if (!prop)
return;
ret = do_get_kexec_buffer(prop, len, &addr, &size);
fdt_delprop(fdt, chosen_node, "linux,ima-kexec-buffer");
if (ret)
return;
ret = delete_fdt_mem_rsv(fdt, addr, size);
if (!ret)
pr_debug("Removed old IMA buffer reservation.\n");
}
#ifdef CONFIG_IMA_KEXEC
/**
* arch_ima_add_kexec_buffer - do arch-specific steps to add the IMA buffer
*
* Architectures should use this function to pass on the IMA buffer
* information to the next kernel.
*
* Return: 0 on success, negative errno on error.
*/
int arch_ima_add_kexec_buffer(struct kimage *image, unsigned long load_addr,
size_t size)
{
image->arch.ima_buffer_addr = load_addr;
image->arch.ima_buffer_size = size;
return 0;
}
static int write_number(void *p, u64 value, int cells)
{
if (cells == 1) {
u32 tmp;
if (value > U32_MAX)
return -EINVAL;
tmp = cpu_to_be32(value);
memcpy(p, &tmp, sizeof(tmp));
} else if (cells == 2) {
u64 tmp;
tmp = cpu_to_be64(value);
memcpy(p, &tmp, sizeof(tmp));
} else
return -EINVAL;
return 0;
}
/**
* setup_ima_buffer - add IMA buffer information to the fdt
* @image: kexec image being loaded.
* @fdt: Flattened device tree for the next kernel.
* @chosen_node: Offset to the chosen node.
*
* Return: 0 on success, or negative errno on error.
*/
int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node)
{
int ret, addr_cells, size_cells, entry_size;
u8 value[16];
remove_ima_buffer(fdt, chosen_node);
if (!image->arch.ima_buffer_size)
return 0;
ret = get_addr_size_cells(&addr_cells, &size_cells);
if (ret)
return ret;
entry_size = 4 * (addr_cells + size_cells);
if (entry_size > sizeof(value))
return -EINVAL;
ret = write_number(value, image->arch.ima_buffer_addr, addr_cells);
if (ret)
return ret;
ret = write_number(value + 4 * addr_cells, image->arch.ima_buffer_size,
size_cells);
if (ret)
return ret;
ret = fdt_setprop(fdt, chosen_node, "linux,ima-kexec-buffer", value,
entry_size);
if (ret < 0)
return -EINVAL;
ret = fdt_add_mem_rsv(fdt, image->arch.ima_buffer_addr,
image->arch.ima_buffer_size);
if (ret)
return -EINVAL;
pr_debug("IMA buffer at 0x%llx, size = 0x%zx\n",
image->arch.ima_buffer_addr, image->arch.ima_buffer_size);
return 0;
}
#endif /* CONFIG_IMA_KEXEC */

View File

@ -150,11 +150,6 @@ struct kimage_arch {
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
/* Core ELF header buffer */
void *elf_headers;
unsigned long elf_headers_sz;
unsigned long elf_load_addr;
};
#endif /* CONFIG_X86_32 */

View File

@ -323,8 +323,8 @@ static int memmap_exclude_ranges(struct kimage *image, struct crash_mem *cmem,
cmem->nr_ranges = 1;
/* Exclude elf header region */
start = image->arch.elf_load_addr;
end = start + image->arch.elf_headers_sz - 1;
start = image->elf_load_addr;
end = start + image->elf_headers_sz - 1;
return crash_exclude_mem_range(cmem, start, end);
}
@ -407,20 +407,20 @@ int crash_load_segments(struct kimage *image)
if (ret)
return ret;
image->arch.elf_headers = kbuf.buffer;
image->arch.elf_headers_sz = kbuf.bufsz;
image->elf_headers = kbuf.buffer;
image->elf_headers_sz = kbuf.bufsz;
kbuf.memsz = kbuf.bufsz;
kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
ret = kexec_add_buffer(&kbuf);
if (ret) {
vfree((void *)image->arch.elf_headers);
vfree((void *)image->elf_headers);
return ret;
}
image->arch.elf_load_addr = kbuf.mem;
image->elf_load_addr = kbuf.mem;
pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
image->arch.elf_load_addr, kbuf.bufsz, kbuf.bufsz);
image->elf_load_addr, kbuf.bufsz, kbuf.bufsz);
return ret;
}

View File

@ -75,7 +75,7 @@ static int setup_cmdline(struct kimage *image, struct boot_params *params,
if (image->type == KEXEC_TYPE_CRASH) {
len = sprintf(cmdline_ptr,
"elfcorehdr=0x%lx ", image->arch.elf_load_addr);
"elfcorehdr=0x%lx ", image->elf_load_addr);
}
memcpy(cmdline_ptr + len, cmdline, cmdline_len);
cmdline_len += len;

View File

@ -402,8 +402,8 @@ void machine_kexec(struct kimage *image)
#ifdef CONFIG_KEXEC_FILE
void *arch_kexec_kernel_image_load(struct kimage *image)
{
vfree(image->arch.elf_headers);
image->arch.elf_headers = NULL;
vfree(image->elf_headers);
image->elf_headers = NULL;
if (!image->fops || !image->fops->load)
return ERR_PTR(-ENOEXEC);

View File

@ -14,4 +14,10 @@ obj-$(CONFIG_OF_RESOLVE) += resolver.o
obj-$(CONFIG_OF_OVERLAY) += overlay.o
obj-$(CONFIG_OF_NUMA) += of_numa.o
ifdef CONFIG_KEXEC_FILE
ifdef CONFIG_OF_FLATTREE
obj-y += kexec.o
endif
endif
obj-$(CONFIG_OF_UNITTEST) += unittest-data/

View File

@ -117,9 +117,12 @@ static unsigned int of_bus_pci_get_flags(const __be32 *addr)
flags |= IORESOURCE_IO;
break;
case 0x02: /* 32 bits */
case 0x03: /* 64 bits */
flags |= IORESOURCE_MEM;
break;
case 0x03: /* 64 bits */
flags |= IORESOURCE_MEM | IORESOURCE_MEM_64;
break;
}
if (w & 0x40000000)
flags |= IORESOURCE_PREFETCH;
@ -861,6 +864,9 @@ static int __of_address_to_resource(struct device_node *dev,
/**
* of_address_to_resource - Translate device tree address and return as resource
* @dev: Caller's Device Node
* @index: Index into the array
* @r: Pointer to resource array
*
* Note that if your address is a PIO address, the conversion will fail if
* the physical address can't be internally converted to an IO token with

View File

@ -244,7 +244,7 @@ struct device_node *__of_find_all_nodes(struct device_node *prev)
* @prev: Previous node or NULL to start iteration
* of_node_put() will be called on it
*
* Returns a node pointer with refcount incremented, use
* Return: A node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
struct device_node *of_find_all_nodes(struct device_node *prev)
@ -305,7 +305,7 @@ bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id)
return (u32)phys_id == cpu;
}
/**
/*
* Checks if the given "prop_name" property holds the physical id of the
* core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not
* NULL, local thread number within the core is returned in it.
@ -374,7 +374,7 @@ bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun,
* before booting secondary cores. This function uses arch_match_cpu_phys_id
* which can be overridden by architecture specific implementation.
*
* Returns a node pointer for the logical cpu with refcount incremented, use
* Return: A node pointer for the logical cpu with refcount incremented, use
* of_node_put() on it when done. Returns NULL if not found.
*/
struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
@ -394,8 +394,8 @@ EXPORT_SYMBOL(of_get_cpu_node);
*
* @cpu_node: Pointer to the device_node for CPU.
*
* Returns the logical CPU number of the given CPU device_node.
* Returns -ENODEV if the CPU is not found.
* Return: The logical CPU number of the given CPU device_node or -ENODEV if the
* CPU is not found.
*/
int of_cpu_node_to_id(struct device_node *cpu_node)
{
@ -427,7 +427,7 @@ EXPORT_SYMBOL(of_cpu_node_to_id);
* bindings. This function check for both and returns the idle state node for
* the requested index.
*
* In case an idle state node is found at @index, the refcount is incremented
* Return: An idle state node if found at @index. The refcount is incremented
* for it, so call of_node_put() on it when done. Returns NULL if not found.
*/
struct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
@ -561,7 +561,7 @@ int of_device_compatible_match(struct device_node *device,
* of_machine_is_compatible - Test root of device tree for a given compatible value
* @compat: compatible string to look for in root node's compatible property.
*
* Returns a positive integer if the root node has the given value in its
* Return: A positive integer if the root node has the given value in its
* compatible property.
*/
int of_machine_is_compatible(const char *compat)
@ -583,7 +583,7 @@ EXPORT_SYMBOL(of_machine_is_compatible);
*
* @device: Node to check for availability, with locks already held
*
* Returns true if the status property is absent or set to "okay" or "ok",
* Return: True if the status property is absent or set to "okay" or "ok",
* false otherwise
*/
static bool __of_device_is_available(const struct device_node *device)
@ -611,7 +611,7 @@ static bool __of_device_is_available(const struct device_node *device)
*
* @device: Node to check for availability
*
* Returns true if the status property is absent or set to "okay" or "ok",
* Return: True if the status property is absent or set to "okay" or "ok",
* false otherwise
*/
bool of_device_is_available(const struct device_node *device)
@ -632,7 +632,7 @@ EXPORT_SYMBOL(of_device_is_available);
*
* @device: Node to check for endianness
*
* Returns true if the device has a "big-endian" property, or if the kernel
* Return: True if the device has a "big-endian" property, or if the kernel
* was compiled for BE *and* the device has a "native-endian" property.
* Returns false otherwise.
*
@ -651,11 +651,11 @@ bool of_device_is_big_endian(const struct device_node *device)
EXPORT_SYMBOL(of_device_is_big_endian);
/**
* of_get_parent - Get a node's parent if any
* @node: Node to get parent
* of_get_parent - Get a node's parent if any
* @node: Node to get parent
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
* Return: A node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
struct device_node *of_get_parent(const struct device_node *node)
{
@ -673,15 +673,15 @@ struct device_node *of_get_parent(const struct device_node *node)
EXPORT_SYMBOL(of_get_parent);
/**
* of_get_next_parent - Iterate to a node's parent
* @node: Node to get parent of
* of_get_next_parent - Iterate to a node's parent
* @node: Node to get parent of
*
* This is like of_get_parent() except that it drops the
* refcount on the passed node, making it suitable for iterating
* through a node's parents.
* This is like of_get_parent() except that it drops the
* refcount on the passed node, making it suitable for iterating
* through a node's parents.
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
* Return: A node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
struct device_node *of_get_next_parent(struct device_node *node)
{
@ -719,13 +719,13 @@ static struct device_node *__of_get_next_child(const struct device_node *node,
child = __of_get_next_child(parent, child))
/**
* of_get_next_child - Iterate a node childs
* @node: parent node
* @prev: previous child of the parent node, or NULL to get first
* of_get_next_child - Iterate a node childs
* @node: parent node
* @prev: previous child of the parent node, or NULL to get first
*
* Returns a node pointer with refcount incremented, use of_node_put() on
* it when done. Returns NULL when prev is the last child. Decrements the
* refcount of prev.
* Return: A node pointer with refcount incremented, use of_node_put() on
* it when done. Returns NULL when prev is the last child. Decrements the
* refcount of prev.
*/
struct device_node *of_get_next_child(const struct device_node *node,
struct device_node *prev)
@ -741,12 +741,12 @@ struct device_node *of_get_next_child(const struct device_node *node,
EXPORT_SYMBOL(of_get_next_child);
/**
* of_get_next_available_child - Find the next available child node
* @node: parent node
* @prev: previous child of the parent node, or NULL to get first
* of_get_next_available_child - Find the next available child node
* @node: parent node
* @prev: previous child of the parent node, or NULL to get first
*
* This function is like of_get_next_child(), except that it
* automatically skips any disabled nodes (i.e. status = "disabled").
* This function is like of_get_next_child(), except that it
* automatically skips any disabled nodes (i.e. status = "disabled").
*/
struct device_node *of_get_next_available_child(const struct device_node *node,
struct device_node *prev)
@ -772,12 +772,12 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
EXPORT_SYMBOL(of_get_next_available_child);
/**
* of_get_next_cpu_node - Iterate on cpu nodes
* @prev: previous child of the /cpus node, or NULL to get first
* of_get_next_cpu_node - Iterate on cpu nodes
* @prev: previous child of the /cpus node, or NULL to get first
*
* Returns a cpu node pointer with refcount incremented, use of_node_put()
* on it when done. Returns NULL when prev is the last child. Decrements
* the refcount of prev.
* Return: A cpu node pointer with refcount incremented, use of_node_put()
* on it when done. Returns NULL when prev is the last child. Decrements
* the refcount of prev.
*/
struct device_node *of_get_next_cpu_node(struct device_node *prev)
{
@ -816,7 +816,7 @@ EXPORT_SYMBOL(of_get_next_cpu_node);
* Lookup child node whose compatible property contains the given compatible
* string.
*
* Returns a node pointer with refcount incremented, use of_node_put() on it
* Return: a node pointer with refcount incremented, use of_node_put() on it
* when done; or NULL if not found.
*/
struct device_node *of_get_compatible_child(const struct device_node *parent,
@ -834,15 +834,15 @@ struct device_node *of_get_compatible_child(const struct device_node *parent,
EXPORT_SYMBOL(of_get_compatible_child);
/**
* of_get_child_by_name - Find the child node by name for a given parent
* @node: parent node
* @name: child name to look for.
* of_get_child_by_name - Find the child node by name for a given parent
* @node: parent node
* @name: child name to look for.
*
* This function looks for child node for given matching name
* This function looks for child node for given matching name
*
* Returns a node pointer if found, with refcount incremented, use
* of_node_put() on it when done.
* Returns NULL if node is not found.
* Return: A node pointer if found, with refcount incremented, use
* of_node_put() on it when done.
* Returns NULL if node is not found.
*/
struct device_node *of_get_child_by_name(const struct device_node *node,
const char *name)
@ -893,22 +893,22 @@ struct device_node *__of_find_node_by_full_path(struct device_node *node,
}
/**
* of_find_node_opts_by_path - Find a node matching a full OF path
* @path: Either the full path to match, or if the path does not
* start with '/', the name of a property of the /aliases
* node (an alias). In the case of an alias, the node
* matching the alias' value will be returned.
* @opts: Address of a pointer into which to store the start of
* an options string appended to the end of the path with
* a ':' separator.
* of_find_node_opts_by_path - Find a node matching a full OF path
* @path: Either the full path to match, or if the path does not
* start with '/', the name of a property of the /aliases
* node (an alias). In the case of an alias, the node
* matching the alias' value will be returned.
* @opts: Address of a pointer into which to store the start of
* an options string appended to the end of the path with
* a ':' separator.
*
* Valid paths:
* /foo/bar Full path
* foo Valid alias
* foo/bar Valid alias + relative path
* Valid paths:
* * /foo/bar Full path
* * foo Valid alias
* * foo/bar Valid alias + relative path
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
* Return: A node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
struct device_node *of_find_node_opts_by_path(const char *path, const char **opts)
{
@ -958,15 +958,15 @@ struct device_node *of_find_node_opts_by_path(const char *path, const char **opt
EXPORT_SYMBOL(of_find_node_opts_by_path);
/**
* of_find_node_by_name - Find a node by its "name" property
* @from: The node to start searching from or NULL; the node
* of_find_node_by_name - Find a node by its "name" property
* @from: The node to start searching from or NULL; the node
* you pass will not be searched, only the next one
* will. Typically, you pass what the previous call
* returned. of_node_put() will be called on @from.
* @name: The name string to match against
* @name: The name string to match against
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
* Return: A node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
struct device_node *of_find_node_by_name(struct device_node *from,
const char *name)
@ -985,16 +985,16 @@ struct device_node *of_find_node_by_name(struct device_node *from,
EXPORT_SYMBOL(of_find_node_by_name);
/**
* of_find_node_by_type - Find a node by its "device_type" property
* @from: The node to start searching from, or NULL to start searching
* of_find_node_by_type - Find a node by its "device_type" property
* @from: The node to start searching from, or NULL to start searching
* the entire device tree. The node you pass will not be
* searched, only the next one will; typically, you pass
* what the previous call returned. of_node_put() will be
* called on from for you.
* @type: The type string to match against
* @type: The type string to match against
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
* Return: A node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
struct device_node *of_find_node_by_type(struct device_node *from,
const char *type)
@ -1013,18 +1013,18 @@ struct device_node *of_find_node_by_type(struct device_node *from,
EXPORT_SYMBOL(of_find_node_by_type);
/**
* of_find_compatible_node - Find a node based on type and one of the
* of_find_compatible_node - Find a node based on type and one of the
* tokens in its "compatible" property
* @from: The node to start searching from or NULL, the node
* you pass will not be searched, only the next one
* will; typically, you pass what the previous call
* returned. of_node_put() will be called on it
* @type: The type string to match "device_type" or NULL to ignore
* @compatible: The string to match to one of the tokens in the device
* "compatible" list.
* @from: The node to start searching from or NULL, the node
* you pass will not be searched, only the next one
* will; typically, you pass what the previous call
* returned. of_node_put() will be called on it
* @type: The type string to match "device_type" or NULL to ignore
* @compatible: The string to match to one of the tokens in the device
* "compatible" list.
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
* Return: A node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
struct device_node *of_find_compatible_node(struct device_node *from,
const char *type, const char *compatible)
@ -1044,16 +1044,16 @@ struct device_node *of_find_compatible_node(struct device_node *from,
EXPORT_SYMBOL(of_find_compatible_node);
/**
* of_find_node_with_property - Find a node which has a property with
* the given name.
* @from: The node to start searching from or NULL, the node
* you pass will not be searched, only the next one
* will; typically, you pass what the previous call
* returned. of_node_put() will be called on it
* @prop_name: The name of the property to look for.
* of_find_node_with_property - Find a node which has a property with
* the given name.
* @from: The node to start searching from or NULL, the node
* you pass will not be searched, only the next one
* will; typically, you pass what the previous call
* returned. of_node_put() will be called on it
* @prop_name: The name of the property to look for.
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
* Return: A node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
struct device_node *of_find_node_with_property(struct device_node *from,
const char *prop_name)
@ -1102,10 +1102,10 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches,
/**
* of_match_node - Tell if a device_node has a matching of_match structure
* @matches: array of of device match structures to search in
* @node: the of device structure to match against
* @matches: array of of device match structures to search in
* @node: the of device structure to match against
*
* Low level utility function used by device matching.
* Low level utility function used by device matching.
*/
const struct of_device_id *of_match_node(const struct of_device_id *matches,
const struct device_node *node)
@ -1121,17 +1121,17 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
EXPORT_SYMBOL(of_match_node);
/**
* of_find_matching_node_and_match - Find a node based on an of_device_id
* match table.
* @from: The node to start searching from or NULL, the node
* you pass will not be searched, only the next one
* will; typically, you pass what the previous call
* returned. of_node_put() will be called on it
* @matches: array of of device match structures to search in
* @match Updated to point at the matches entry which matched
* of_find_matching_node_and_match - Find a node based on an of_device_id
* match table.
* @from: The node to start searching from or NULL, the node
* you pass will not be searched, only the next one
* will; typically, you pass what the previous call
* returned. of_node_put() will be called on it
* @matches: array of of device match structures to search in
* @match: Updated to point at the matches entry which matched
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
* Return: A node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
struct device_node *of_find_matching_node_and_match(struct device_node *from,
const struct of_device_id *matches,
@ -1170,7 +1170,7 @@ EXPORT_SYMBOL(of_find_matching_node_and_match);
* It does this by stripping the manufacturer prefix (as delimited by a ',')
* from the first entry in the compatible list property.
*
* This routine returns 0 on success, <0 on failure.
* Return: This routine returns 0 on success, <0 on failure.
*/
int of_modalias_node(struct device_node *node, char *modalias, int len)
{
@ -1190,7 +1190,7 @@ EXPORT_SYMBOL_GPL(of_modalias_node);
* of_find_node_by_phandle - Find a node given a phandle
* @handle: phandle of the node to find
*
* Returns a node pointer with refcount incremented, use
* Return: A node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
struct device_node *of_find_node_by_phandle(phandle handle)
@ -1426,7 +1426,7 @@ static int __of_parse_phandle_with_args(const struct device_node *np,
* @index: For properties holding a table of phandles, this is the index into
* the table
*
* Returns the device_node pointer with refcount incremented. Use
* Return: The device_node pointer with refcount incremented. Use
* of_node_put() on it when done.
*/
struct device_node *of_parse_phandle(const struct device_node *np,
@ -1460,21 +1460,21 @@ EXPORT_SYMBOL(of_parse_phandle);
* Caller is responsible to call of_node_put() on the returned out_args->np
* pointer.
*
* Example:
* Example::
*
* phandle1: node1 {
* phandle1: node1 {
* #list-cells = <2>;
* }
* };
*
* phandle2: node2 {
* phandle2: node2 {
* #list-cells = <1>;
* }
* };
*
* node3 {
* node3 {
* list = <&phandle1 1 2 &phandle2 3>;
* }
* };
*
* To get a device_node of the `node2' node you may call this:
* To get a device_node of the ``node2`` node you may call this:
* of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
*/
int of_parse_phandle_with_args(const struct device_node *np, const char *list_name,
@ -1512,29 +1512,29 @@ EXPORT_SYMBOL(of_parse_phandle_with_args);
* Caller is responsible to call of_node_put() on the returned out_args->np
* pointer.
*
* Example:
* Example::
*
* phandle1: node1 {
* #list-cells = <2>;
* }
* phandle1: node1 {
* #list-cells = <2>;
* };
*
* phandle2: node2 {
* #list-cells = <1>;
* }
* phandle2: node2 {
* #list-cells = <1>;
* };
*
* phandle3: node3 {
* #list-cells = <1>;
* list-map = <0 &phandle2 3>,
* <1 &phandle2 2>,
* <2 &phandle1 5 1>;
* list-map-mask = <0x3>;
* };
* phandle3: node3 {
* #list-cells = <1>;
* list-map = <0 &phandle2 3>,
* <1 &phandle2 2>,
* <2 &phandle1 5 1>;
* list-map-mask = <0x3>;
* };
*
* node4 {
* list = <&phandle1 1 2 &phandle3 0>;
* }
* node4 {
* list = <&phandle1 1 2 &phandle3 0>;
* };
*
* To get a device_node of the `node2' node you may call this:
* To get a device_node of the ``node2`` node you may call this:
* of_parse_phandle_with_args(node4, "list", "list", 1, &args);
*/
int of_parse_phandle_with_args_map(const struct device_node *np,
@ -1694,19 +1694,19 @@ EXPORT_SYMBOL(of_parse_phandle_with_args_map);
* Caller is responsible to call of_node_put() on the returned out_args->np
* pointer.
*
* Example:
* Example::
*
* phandle1: node1 {
* }
* phandle1: node1 {
* };
*
* phandle2: node2 {
* }
* phandle2: node2 {
* };
*
* node3 {
* list = <&phandle1 0 2 &phandle2 2 3>;
* }
* node3 {
* list = <&phandle1 0 2 &phandle2 2 3>;
* };
*
* To get a device_node of the `node2' node you may call this:
* To get a device_node of the ``node2`` node you may call this:
* of_parse_phandle_with_fixed_args(node3, "list", 2, 1, &args);
*/
int of_parse_phandle_with_fixed_args(const struct device_node *np,
@ -1726,7 +1726,7 @@ EXPORT_SYMBOL(of_parse_phandle_with_fixed_args);
* @list_name: property name that contains a list
* @cells_name: property name that specifies phandles' arguments count
*
* Returns the number of phandle + argument tuples within a property. It
* Return: The number of phandle + argument tuples within a property. It
* is a typical pattern to encode a list of phandle and variable
* arguments into a single property. The number of arguments is encoded
* by a property in the phandle-target node. For example, a gpios
@ -1774,6 +1774,8 @@ EXPORT_SYMBOL(of_count_phandle_with_args);
/**
* __of_add_property - Add a property to a node without lock operations
* @np: Caller's Device Node
* @prop: Property to add
*/
int __of_add_property(struct device_node *np, struct property *prop)
{
@ -1795,6 +1797,8 @@ int __of_add_property(struct device_node *np, struct property *prop)
/**
* of_add_property - Add a property to a node
* @np: Caller's Device Node
* @prop: Property to add
*/
int of_add_property(struct device_node *np, struct property *prop)
{
@ -1839,6 +1843,8 @@ int __of_remove_property(struct device_node *np, struct property *prop)
/**
* of_remove_property - Remove a property from a node.
* @np: Caller's Device Node
* @prop: Property to remove
*
* Note that we don't actually remove it, since we have given out
* who-knows-how-many pointers to the data using get-property.
@ -1946,13 +1952,12 @@ static void of_alias_add(struct alias_prop *ap, struct device_node *np,
/**
* of_alias_scan - Scan all properties of the 'aliases' node
* @dt_alloc: An allocator that provides a virtual address to memory
* for storing the resulting tree
*
* The function scans all the properties of the 'aliases' node and populates
* the global lookup table with the properties. It returns the
* number of alias properties found, or an error code in case of failure.
*
* @dt_alloc: An allocator that provides a virtual address to memory
* for storing the resulting tree
*/
void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
{
@ -2021,7 +2026,9 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
* @stem: Alias stem of the given device_node
*
* The function travels the lookup table to get the alias id for the given
* device_node and alias stem. It returns the alias id if found.
* device_node and alias stem.
*
* Return: The alias id if found.
*/
int of_alias_get_id(struct device_node *np, const char *stem)
{
@ -2125,13 +2132,14 @@ EXPORT_SYMBOL_GPL(of_alias_get_highest_id);
/**
* of_console_check() - Test and setup console for DT setup
* @dn - Pointer to device node
* @name - Name to use for preferred console without index. ex. "ttyS"
* @index - Index to use for preferred console.
* @dn: Pointer to device node
* @name: Name to use for preferred console without index. ex. "ttyS"
* @index: Index to use for preferred console.
*
* Check if the given device node matches the stdout-path property in the
* /chosen node. If it does then register it as the preferred console and return
* TRUE. Otherwise return FALSE.
* /chosen node. If it does then register it as the preferred console.
*
* Return: TRUE if console successfully setup. Otherwise return FALSE.
*/
bool of_console_check(struct device_node *dn, char *name, int index)
{
@ -2147,12 +2155,12 @@ bool of_console_check(struct device_node *dn, char *name, int index)
EXPORT_SYMBOL_GPL(of_console_check);
/**
* of_find_next_cache_node - Find a node's subsidiary cache
* @np: node of type "cpu" or "cache"
* of_find_next_cache_node - Find a node's subsidiary cache
* @np: node of type "cpu" or "cache"
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done. Caller should hold a reference
* to np.
* Return: A node pointer with refcount incremented, use
* of_node_put() on it when done. Caller should hold a reference
* to np.
*/
struct device_node *of_find_next_cache_node(const struct device_node *np)
{
@ -2182,7 +2190,7 @@ struct device_node *of_find_next_cache_node(const struct device_node *np)
*
* @cpu: cpu number(logical index) for which the last cache level is needed
*
* Returns the the level at which the last cache is present. It is exactly
* Return: The the level at which the last cache is present. It is exactly
* same as the total number of cache levels for the given logical cpu.
*/
int of_find_last_cache_level(unsigned int cpu)

View File

@ -53,7 +53,7 @@ int of_device_add(struct platform_device *ofdev)
}
/**
* of_dma_configure - Setup DMA configuration
* of_dma_configure_id - Setup DMA configuration
* @dev: Device to apply DMA configuration
* @np: Pointer to OF node having DMA configuration
* @force_dma: Whether device is to be set up by of_dma_configure() even if
@ -258,6 +258,9 @@ EXPORT_SYMBOL_GPL(of_device_request_module);
/**
* of_device_modalias - Fill buffer with newline terminated modalias string
* @dev: Calling device
* @str: Modalias string
* @len: Size of @str
*/
ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len)
{
@ -275,6 +278,8 @@ EXPORT_SYMBOL_GPL(of_device_modalias);
/**
* of_device_uevent - Display OF related uevent information
* @dev: Device to apply DMA configuration
* @env: Kernel object's userspace event reference
*/
void of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
{

View File

@ -27,7 +27,7 @@ static struct device_node *kobj_to_device_node(struct kobject *kobj)
* @node: Node to inc refcount, NULL is supported to simplify writing of
* callers
*
* Returns node.
* Return: The node with refcount incremented.
*/
struct device_node *of_node_get(struct device_node *node)
{
@ -104,7 +104,8 @@ int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p)
* @arg - argument of the of notifier
*
* Returns the new state of a device based on the notifier used.
* Returns 0 on device going from enabled to disabled, 1 on device
*
* Return: 0 on device going from enabled to disabled, 1 on device
* going from disabled to enabled and -1 on no change.
*/
int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr)
@ -229,6 +230,7 @@ static void __of_attach_node(struct device_node *np)
/**
* of_attach_node() - Plug a device node into the tree and global list.
* @np: Pointer to the caller's Device Node
*/
int of_attach_node(struct device_node *np)
{
@ -281,6 +283,7 @@ void __of_detach_node(struct device_node *np)
/**
* of_detach_node() - "Unplug" a node from the device tree.
* @np: Pointer to the caller's Device Node
*/
int of_detach_node(struct device_node *np)
{
@ -318,7 +321,7 @@ static void property_list_free(struct property *prop_list)
/**
* of_node_release() - release a dynamically allocated node
* @kref: kref element of the node to be released
* @kobj: kernel object of the node to be released
*
* In of_node_put() this function is passed to kref_put() as the destructor.
*/
@ -372,7 +375,8 @@ void of_node_release(struct kobject *kobj)
* property structure and the property name & contents. The property's
* flags have the OF_DYNAMIC bit set so that we can differentiate between
* dynamically allocated properties and not.
* Returns the newly allocated property or NULL on out of memory error.
*
* Return: The newly allocated property or NULL on out of memory error.
*/
struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
{
@ -415,7 +419,7 @@ struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
* another node. The node data are dynamically allocated and all the node
* flags have the OF_DYNAMIC & OF_DETACHED bits set.
*
* Returns the newly allocated node or NULL on out of memory error.
* Return: The newly allocated node or NULL on out of memory error.
*/
struct device_node *__of_node_dup(const struct device_node *np,
const char *full_name)
@ -781,7 +785,8 @@ static int __of_changeset_apply(struct of_changeset *ocs)
* Any side-effects of live tree state changes are applied here on
* success, like creation/destruction of devices and side-effects
* like creation of sysfs properties and directories.
* Returns 0 on success, a negative error value in case of an error.
*
* Return: 0 on success, a negative error value in case of an error.
* On error the partially applied effects are reverted.
*/
int of_changeset_apply(struct of_changeset *ocs)
@ -875,7 +880,8 @@ static int __of_changeset_revert(struct of_changeset *ocs)
* was before the application.
* Any side-effects like creation/destruction of devices and
* removal of sysfs properties and directories are applied.
* Returns 0 on success, a negative error value in case of an error.
*
* Return: 0 on success, a negative error value in case of an error.
*/
int of_changeset_revert(struct of_changeset *ocs)
{
@ -903,7 +909,8 @@ EXPORT_SYMBOL_GPL(of_changeset_revert);
* + OF_RECONFIG_ADD_PROPERTY
* + OF_RECONFIG_REMOVE_PROPERTY,
* + OF_RECONFIG_UPDATE_PROPERTY
* Returns 0 on success, a negative error value in case of an error.
*
* Return: 0 on success, a negative error value in case of an error.
*/
int of_changeset_action(struct of_changeset *ocs, unsigned long action,
struct device_node *np, struct property *prop)

View File

@ -282,7 +282,7 @@ static void reverse_nodes(struct device_node *parent)
* @dad: Parent struct device_node
* @nodepp: The device_node tree created by the call
*
* It returns the size of unflattened device tree or error code
* Return: The size of unflattened device tree or error code
*/
static int unflatten_dt_nodes(const void *blob,
void *mem,
@ -351,11 +351,6 @@ static int unflatten_dt_nodes(const void *blob,
/**
* __unflatten_device_tree - create tree of device_nodes from flat blob
*
* unflattens a device-tree, creating the
* tree of struct device_node. It also fills the "name" and "type"
* pointers of the nodes so the normal device-tree walking functions
* can be used.
* @blob: The blob to expand
* @dad: Parent device node
* @mynodes: The device_node tree created by the call
@ -363,7 +358,11 @@ static int unflatten_dt_nodes(const void *blob,
* for the resulting tree
* @detached: if true set OF_DETACHED on @mynodes
*
* Returns NULL on failure or the memory chunk containing the unflattened
* unflattens a device-tree, creating the tree of struct device_node. It also
* fills the "name" and "type" pointers of the nodes so the normal device-tree
* walking functions can be used.
*
* Return: NULL on failure or the memory chunk containing the unflattened
* device tree on success.
*/
void *__unflatten_device_tree(const void *blob,
@ -452,7 +451,7 @@ static DEFINE_MUTEX(of_fdt_unflatten_mutex);
* pointers of the nodes so the normal device-tree walking functions
* can be used.
*
* Returns NULL on failure or the memory chunk containing the unflattened
* Return: NULL on failure or the memory chunk containing the unflattened
* device tree on success.
*/
void *of_fdt_unflatten_tree(const unsigned long *blob,
@ -480,7 +479,7 @@ void *initial_boot_params __ro_after_init;
static u32 of_fdt_crc32;
/**
/*
* __reserved_mem_reserve_reg() - reserve all memory described in 'reg' property
*/
static int __init __reserved_mem_reserve_reg(unsigned long node,
@ -526,7 +525,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
return 0;
}
/**
/*
* __reserved_mem_check_root() - check if #size-cells, #address-cells provided
* in /reserved-memory matches the values supported by the current implementation,
* also check if ranges property has been provided
@ -549,8 +548,8 @@ static int __init __reserved_mem_check_root(unsigned long node)
return 0;
}
/**
* fdt_scan_reserved_mem() - scan a single FDT node for reserved memory
/*
* __fdt_scan_reserved_mem() - scan a single FDT node for reserved memory
*/
static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname,
int depth, void *data)
@ -660,6 +659,7 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
/**
* of_scan_flat_dt_subnodes - scan sub-nodes of a node call callback on each.
* @parent: parent node
* @it: callback function
* @data: context data pointer
*
@ -699,7 +699,7 @@ int __init of_get_flat_dt_subnode_by_name(unsigned long node, const char *uname)
return fdt_subnode_offset(initial_boot_params, node, uname);
}
/**
/*
* of_get_flat_dt_root - find the root node in the flat blob
*/
unsigned long __init of_get_flat_dt_root(void)
@ -707,7 +707,7 @@ unsigned long __init of_get_flat_dt_root(void)
return 0;
}
/**
/*
* of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr
*
* This function can be used within scan_flattened_dt callback to get
@ -726,7 +726,7 @@ const void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
* @node: node to test
* @compat: compatible string to compare with compatible list.
*
* On match, returns a non-zero value with smaller values returned for more
* Return: a non-zero value on match with smaller values returned for more
* specific compatible values.
*/
static int of_fdt_is_compatible(const void *blob,
@ -761,7 +761,7 @@ int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
return of_fdt_is_compatible(initial_boot_params, node, compat);
}
/**
/*
* of_flat_dt_match - Return true if node matches a list of compatible values
*/
static int __init of_flat_dt_match(unsigned long node, const char *const *compat)
@ -781,8 +781,8 @@ static int __init of_flat_dt_match(unsigned long node, const char *const *compat
return score;
}
/**
* of_get_flat_dt_prop - Given a node in the flat blob, return the phandle
/*
* of_get_flat_dt_phandle - Given a node in the flat blob, return the phandle
*/
uint32_t __init of_get_flat_dt_phandle(unsigned long node)
{
@ -957,7 +957,7 @@ int __init early_init_dt_scan_chosen_stdout(void)
}
#endif
/**
/*
* early_init_dt_scan_root - fetch the top level address and size cells
*/
int __init early_init_dt_scan_root(unsigned long node, const char *uname,
@ -993,7 +993,7 @@ u64 __init dt_mem_next_cell(int s, const __be32 **cellp)
return of_read_number(p, s);
}
/**
/*
* early_init_dt_scan_memory - Look for and parse memory nodes
*/
int __init early_init_dt_scan_memory(unsigned long node, const char *uname,

View File

@ -48,7 +48,7 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
* of_irq_find_parent - Given a device node, find its interrupt parent node
* @child: pointer to device node
*
* Returns a pointer to the interrupt parent node, or NULL if the interrupt
* Return: A pointer to the interrupt parent node, or NULL if the interrupt
* parent could not be determined.
*/
struct device_node *of_irq_find_parent(struct device_node *child)
@ -81,14 +81,14 @@ EXPORT_SYMBOL_GPL(of_irq_find_parent);
* @addr: address specifier (start of "reg" property of the device) in be32 format
* @out_irq: structure of_phandle_args updated by this function
*
* Returns 0 on success and a negative number on error
*
* This function is a low-level interrupt tree walking function. It
* can be used to do a partial walk with synthetized reg and interrupts
* properties, for example when resolving PCI interrupts when no device
* node exist for the parent. It takes an interrupt specifier structure as
* input, walks the tree looking for any interrupt-map properties, translates
* the specifier for each map, and then returns the translated map.
*
* Return: 0 on success and a negative number on error
*/
int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
{
@ -380,7 +380,7 @@ EXPORT_SYMBOL_GPL(of_irq_to_resource);
* @dev: pointer to device tree node
* @index: zero-based index of the IRQ
*
* Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or
* Return: Linux IRQ number on success, or 0 on the IRQ mapping failure, or
* -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
* of any other failure.
*/
@ -407,7 +407,7 @@ EXPORT_SYMBOL_GPL(of_irq_get);
* @dev: pointer to device tree node
* @name: IRQ name
*
* Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or
* Return: Linux IRQ number on success, or 0 on the IRQ mapping failure, or
* -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
* of any other failure.
*/
@ -447,7 +447,7 @@ int of_irq_count(struct device_node *dev)
* @res: array of resources to fill in
* @nr_irqs: the number of IRQs (and upper bound for num of @res elements)
*
* Returns the size of the filled in table (up to @nr_irqs).
* Return: The size of the filled in table (up to @nr_irqs).
*/
int of_irq_to_resource_table(struct device_node *dev, struct resource *res,
int nr_irqs)
@ -602,7 +602,7 @@ static u32 __of_msi_map_id(struct device *dev, struct device_node **np,
* Walk up the device hierarchy looking for devices with a "msi-map"
* property. If found, apply the mapping to @id_in.
*
* Returns the mapped MSI ID.
* Return: The mapped MSI ID.
*/
u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in)
{

458
drivers/of/kexec.c Normal file
View File

@ -0,0 +1,458 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020 Arm Limited
*
* Based on arch/arm64/kernel/machine_kexec_file.c:
* Copyright (C) 2018 Linaro Limited
*
* And arch/powerpc/kexec/file_load.c:
* Copyright (C) 2016 IBM Corporation
*/
#include <linux/kernel.h>
#include <linux/kexec.h>
#include <linux/memblock.h>
#include <linux/libfdt.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/random.h>
#include <linux/types.h>
/* relevant device tree properties */
#define FDT_PROP_KEXEC_ELFHDR "linux,elfcorehdr"
#define FDT_PROP_MEM_RANGE "linux,usable-memory-range"
#define FDT_PROP_INITRD_START "linux,initrd-start"
#define FDT_PROP_INITRD_END "linux,initrd-end"
#define FDT_PROP_BOOTARGS "bootargs"
#define FDT_PROP_KASLR_SEED "kaslr-seed"
#define FDT_PROP_RNG_SEED "rng-seed"
#define RNG_SEED_SIZE 128
/*
* Additional space needed for the FDT buffer so that we can add initrd,
* bootargs, kaslr-seed, rng-seed, useable-memory-range and elfcorehdr.
*/
#define FDT_EXTRA_SPACE 0x1000
/**
* fdt_find_and_del_mem_rsv - delete memory reservation with given address and size
*
* @fdt: Flattened device tree for the current kernel.
* @start: Starting address of the reserved memory.
* @size: Size of the reserved memory.
*
* Return: 0 on success, or negative errno on error.
*/
static int fdt_find_and_del_mem_rsv(void *fdt, unsigned long start, unsigned long size)
{
int i, ret, num_rsvs = fdt_num_mem_rsv(fdt);
for (i = 0; i < num_rsvs; i++) {
u64 rsv_start, rsv_size;
ret = fdt_get_mem_rsv(fdt, i, &rsv_start, &rsv_size);
if (ret) {
pr_err("Malformed device tree.\n");
return -EINVAL;
}
if (rsv_start == start && rsv_size == size) {
ret = fdt_del_mem_rsv(fdt, i);
if (ret) {
pr_err("Error deleting device tree reservation.\n");
return -EINVAL;
}
return 0;
}
}
return -ENOENT;
}
/**
* get_addr_size_cells - Get address and size of root node
*
* @addr_cells: Return address of the root node
* @size_cells: Return size of the root node
*
* Return: 0 on success, or negative errno on error.
*/
static int get_addr_size_cells(int *addr_cells, int *size_cells)
{
struct device_node *root;
root = of_find_node_by_path("/");
if (!root)
return -EINVAL;
*addr_cells = of_n_addr_cells(root);
*size_cells = of_n_size_cells(root);
of_node_put(root);
return 0;
}
/**
* do_get_kexec_buffer - Get address and size of device tree property
*
* @prop: Device tree property
* @len: Size of @prop
* @addr: Return address of the node
* @size: Return size of the node
*
* Return: 0 on success, or negative errno on error.
*/
static int do_get_kexec_buffer(const void *prop, int len, unsigned long *addr,
size_t *size)
{
int ret, addr_cells, size_cells;
ret = get_addr_size_cells(&addr_cells, &size_cells);
if (ret)
return ret;
if (len < 4 * (addr_cells + size_cells))
return -ENOENT;
*addr = of_read_number(prop, addr_cells);
*size = of_read_number(prop + 4 * addr_cells, size_cells);
return 0;
}
/**
* ima_get_kexec_buffer - get IMA buffer from the previous kernel
* @addr: On successful return, set to point to the buffer contents.
* @size: On successful return, set to the buffer size.
*
* Return: 0 on success, negative errno on error.
*/
int ima_get_kexec_buffer(void **addr, size_t *size)
{
int ret, len;
unsigned long tmp_addr;
size_t tmp_size;
const void *prop;
if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC))
return -ENOTSUPP;
prop = of_get_property(of_chosen, "linux,ima-kexec-buffer", &len);
if (!prop)
return -ENOENT;
ret = do_get_kexec_buffer(prop, len, &tmp_addr, &tmp_size);
if (ret)
return ret;
*addr = __va(tmp_addr);
*size = tmp_size;
return 0;
}
/**
* ima_free_kexec_buffer - free memory used by the IMA buffer
*/
int ima_free_kexec_buffer(void)
{
int ret;
unsigned long addr;
size_t size;
struct property *prop;
if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC))
return -ENOTSUPP;
prop = of_find_property(of_chosen, "linux,ima-kexec-buffer", NULL);
if (!prop)
return -ENOENT;
ret = do_get_kexec_buffer(prop->value, prop->length, &addr, &size);
if (ret)
return ret;
ret = of_remove_property(of_chosen, prop);
if (ret)
return ret;
return memblock_free(addr, size);
}
/**
* remove_ima_buffer - remove the IMA buffer property and reservation from @fdt
*
* @fdt: Flattened Device Tree to update
* @chosen_node: Offset to the chosen node in the device tree
*
* The IMA measurement buffer is of no use to a subsequent kernel, so we always
* remove it from the device tree.
*/
static void remove_ima_buffer(void *fdt, int chosen_node)
{
int ret, len;
unsigned long addr;
size_t size;
const void *prop;
if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC))
return;
prop = fdt_getprop(fdt, chosen_node, "linux,ima-kexec-buffer", &len);
if (!prop)
return;
ret = do_get_kexec_buffer(prop, len, &addr, &size);
fdt_delprop(fdt, chosen_node, "linux,ima-kexec-buffer");
if (ret)
return;
ret = fdt_find_and_del_mem_rsv(fdt, addr, size);
if (!ret)
pr_debug("Removed old IMA buffer reservation.\n");
}
#ifdef CONFIG_IMA_KEXEC
/**
* setup_ima_buffer - add IMA buffer information to the fdt
* @image: kexec image being loaded.
* @fdt: Flattened device tree for the next kernel.
* @chosen_node: Offset to the chosen node.
*
* Return: 0 on success, or negative errno on error.
*/
static int setup_ima_buffer(const struct kimage *image, void *fdt,
int chosen_node)
{
int ret;
if (!image->ima_buffer_size)
return 0;
ret = fdt_appendprop_addrrange(fdt, 0, chosen_node,
"linux,ima-kexec-buffer",
image->ima_buffer_addr,
image->ima_buffer_size);
if (ret < 0)
return -EINVAL;
ret = fdt_add_mem_rsv(fdt, image->ima_buffer_addr,
image->ima_buffer_size);
if (ret)
return -EINVAL;
pr_debug("IMA buffer at 0x%llx, size = 0x%zx\n",
image->ima_buffer_addr, image->ima_buffer_size);
return 0;
}
#else /* CONFIG_IMA_KEXEC */
static inline int setup_ima_buffer(const struct kimage *image, void *fdt,
int chosen_node)
{
return 0;
}
#endif /* CONFIG_IMA_KEXEC */
/*
* of_kexec_alloc_and_setup_fdt - Alloc and setup a new Flattened Device Tree
*
* @image: kexec image being loaded.
* @initrd_load_addr: Address where the next initrd will be loaded.
* @initrd_len: Size of the next initrd, or 0 if there will be none.
* @cmdline: Command line for the next kernel, or NULL if there will
* be none.
* @extra_fdt_size: Additional size for the new FDT buffer.
*
* Return: fdt on success, or NULL errno on error.
*/
void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
unsigned long initrd_load_addr,
unsigned long initrd_len,
const char *cmdline, size_t extra_fdt_size)
{
void *fdt;
int ret, chosen_node;
const void *prop;
size_t fdt_size;
fdt_size = fdt_totalsize(initial_boot_params) +
(cmdline ? strlen(cmdline) : 0) +
FDT_EXTRA_SPACE +
extra_fdt_size;
fdt = kvmalloc(fdt_size, GFP_KERNEL);
if (!fdt)
return NULL;
ret = fdt_open_into(initial_boot_params, fdt, fdt_size);
if (ret < 0) {
pr_err("Error %d setting up the new device tree.\n", ret);
goto out;
}
/* Remove memory reservation for the current device tree. */
ret = fdt_find_and_del_mem_rsv(fdt, __pa(initial_boot_params),
fdt_totalsize(initial_boot_params));
if (ret == -EINVAL) {
pr_err("Error removing memory reservation.\n");
goto out;
}
chosen_node = fdt_path_offset(fdt, "/chosen");
if (chosen_node == -FDT_ERR_NOTFOUND)
chosen_node = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
"chosen");
if (chosen_node < 0) {
ret = chosen_node;
goto out;
}
ret = fdt_delprop(fdt, chosen_node, FDT_PROP_KEXEC_ELFHDR);
if (ret && ret != -FDT_ERR_NOTFOUND)
goto out;
ret = fdt_delprop(fdt, chosen_node, FDT_PROP_MEM_RANGE);
if (ret && ret != -FDT_ERR_NOTFOUND)
goto out;
/* Did we boot using an initrd? */
prop = fdt_getprop(fdt, chosen_node, "linux,initrd-start", NULL);
if (prop) {
u64 tmp_start, tmp_end, tmp_size;
tmp_start = fdt64_to_cpu(*((const fdt64_t *) prop));
prop = fdt_getprop(fdt, chosen_node, "linux,initrd-end", NULL);
if (!prop) {
ret = -EINVAL;
goto out;
}
tmp_end = fdt64_to_cpu(*((const fdt64_t *) prop));
/*
* kexec reserves exact initrd size, while firmware may
* reserve a multiple of PAGE_SIZE, so check for both.
*/
tmp_size = tmp_end - tmp_start;
ret = fdt_find_and_del_mem_rsv(fdt, tmp_start, tmp_size);
if (ret == -ENOENT)
ret = fdt_find_and_del_mem_rsv(fdt, tmp_start,
round_up(tmp_size, PAGE_SIZE));
if (ret == -EINVAL)
goto out;
}
/* add initrd-* */
if (initrd_load_addr) {
ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_INITRD_START,
initrd_load_addr);
if (ret)
goto out;
ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_INITRD_END,
initrd_load_addr + initrd_len);
if (ret)
goto out;
ret = fdt_add_mem_rsv(fdt, initrd_load_addr, initrd_len);
if (ret)
goto out;
} else {
ret = fdt_delprop(fdt, chosen_node, FDT_PROP_INITRD_START);
if (ret && (ret != -FDT_ERR_NOTFOUND))
goto out;
ret = fdt_delprop(fdt, chosen_node, FDT_PROP_INITRD_END);
if (ret && (ret != -FDT_ERR_NOTFOUND))
goto out;
}
if (image->type == KEXEC_TYPE_CRASH) {
/* add linux,elfcorehdr */
ret = fdt_appendprop_addrrange(fdt, 0, chosen_node,
FDT_PROP_KEXEC_ELFHDR,
image->elf_load_addr,
image->elf_headers_sz);
if (ret)
goto out;
/*
* Avoid elfcorehdr from being stomped on in kdump kernel by
* setting up memory reserve map.
*/
ret = fdt_add_mem_rsv(fdt, image->elf_load_addr,
image->elf_headers_sz);
if (ret)
goto out;
/* add linux,usable-memory-range */
ret = fdt_appendprop_addrrange(fdt, 0, chosen_node,
FDT_PROP_MEM_RANGE,
crashk_res.start,
crashk_res.end - crashk_res.start + 1);
if (ret)
goto out;
}
/* add bootargs */
if (cmdline) {
ret = fdt_setprop_string(fdt, chosen_node, FDT_PROP_BOOTARGS, cmdline);
if (ret)
goto out;
} else {
ret = fdt_delprop(fdt, chosen_node, FDT_PROP_BOOTARGS);
if (ret && (ret != -FDT_ERR_NOTFOUND))
goto out;
}
/* add kaslr-seed */
ret = fdt_delprop(fdt, chosen_node, FDT_PROP_KASLR_SEED);
if (ret == -FDT_ERR_NOTFOUND)
ret = 0;
else if (ret)
goto out;
if (rng_is_initialized()) {
u64 seed = get_random_u64();
ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_KASLR_SEED, seed);
if (ret)
goto out;
} else {
pr_notice("RNG is not initialised: omitting \"%s\" property\n",
FDT_PROP_KASLR_SEED);
}
/* add rng-seed */
if (rng_is_initialized()) {
void *rng_seed;
ret = fdt_setprop_placeholder(fdt, chosen_node, FDT_PROP_RNG_SEED,
RNG_SEED_SIZE, &rng_seed);
if (ret)
goto out;
get_random_bytes(rng_seed, RNG_SEED_SIZE);
} else {
pr_notice("RNG is not initialised: omitting \"%s\" property\n",
FDT_PROP_RNG_SEED);
}
ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0);
if (ret)
goto out;
remove_ima_buffer(fdt, chosen_node);
ret = setup_ima_buffer(image, fdt, fdt_path_offset(fdt, "/chosen"));
out:
if (ret) {
kvfree(fdt);
fdt = NULL;
}
return fdt;
}

View File

@ -79,6 +79,9 @@ static const void *of_get_mac_addr_nvmem(struct device_node *np)
}
/**
* of_get_mac_address()
* @np: Caller's Device Node
*
* Search the device tree for the best MAC address to use. 'mac-address' is
* checked first, because that is supposed to contain to "most recent" MAC
* address. If that isn't set, then 'local-mac-address' is checked next,

View File

@ -45,7 +45,7 @@ static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
return memblock_reserve(base, size);
}
/**
/*
* fdt_reserved_mem_save_node() - save fdt node for second pass initialization
*/
void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
@ -67,7 +67,7 @@ void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
return;
}
/**
/*
* __reserved_mem_alloc_size() - allocate reserved memory described by
* 'size', 'alignment' and 'alloc-ranges' properties.
*/
@ -164,7 +164,7 @@ static int __init __reserved_mem_alloc_size(unsigned long node,
static const struct of_device_id __rmem_of_table_sentinel
__used __section("__reservedmem_of_table_end");
/**
/*
* __reserved_mem_init_node() - call region specific reserved memory init code
*/
static int __init __reserved_mem_init_node(struct reserved_mem *rmem)

View File

@ -140,7 +140,7 @@ int of_overlay_notifier_register(struct notifier_block *nb)
EXPORT_SYMBOL_GPL(of_overlay_notifier_register);
/**
* of_overlay_notifier_register() - Unregister notifier for overlay operations
* of_overlay_notifier_unregister() - Unregister notifier for overlay operations
* @nb: Notifier block to unregister
*/
int of_overlay_notifier_unregister(struct notifier_block *nb)
@ -298,7 +298,7 @@ err_free_target_path:
*
* Update of property in symbols node is not allowed.
*
* Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
* Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
* invalid @overlay.
*/
static int add_changeset_property(struct overlay_changeset *ovcs,
@ -403,7 +403,7 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
*
* NOTE_2: Multiple mods of created nodes not supported.
*
* Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
* Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
* invalid @overlay.
*/
static int add_changeset_node(struct overlay_changeset *ovcs,
@ -475,7 +475,7 @@ static int add_changeset_node(struct overlay_changeset *ovcs,
*
* Do not allow symbols node to have any children.
*
* Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
* Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
* invalid @overlay_node.
*/
static int build_changeset_next_level(struct overlay_changeset *ovcs,
@ -606,7 +606,7 @@ static int find_dup_cset_prop(struct overlay_changeset *ovcs,
* the same node or duplicate {add, delete, or update} properties entries
* for the same property.
*
* Returns 0 on success, or -EINVAL if duplicate changeset entry found.
* Return: 0 on success, or -EINVAL if duplicate changeset entry found.
*/
static int changeset_dup_entry_check(struct overlay_changeset *ovcs)
{
@ -630,7 +630,7 @@ static int changeset_dup_entry_check(struct overlay_changeset *ovcs)
* any portions of the changeset that were successfully created will remain
* in @ovcs->cset.
*
* Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
* Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
* invalid overlay in @ovcs->fragments[].
*/
static int build_changeset(struct overlay_changeset *ovcs)
@ -726,7 +726,7 @@ static struct device_node *find_target(struct device_node *info_node)
* the top level of @tree. The relevant top level nodes are the fragment
* nodes and the __symbols__ node. Any other top level node will be ignored.
*
* Returns 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error
* Return: 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error
* detected in @tree, or -ENOSPC if idr_alloc() error.
*/
static int init_overlay_changeset(struct overlay_changeset *ovcs,
@ -796,6 +796,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
if (!fragment->target) {
of_node_put(fragment->overlay);
ret = -EINVAL;
of_node_put(node);
goto err_free_fragments;
}
@ -1186,7 +1187,7 @@ static int overlay_removal_is_ok(struct overlay_changeset *remove_ovcs)
* If an error is returned by an overlay changeset post-remove notifier
* then no further overlay changeset post-remove notifier will be called.
*
* Returns 0 on success, or a negative error number. *ovcs_id is set to
* Return: 0 on success, or a negative error number. *@ovcs_id is set to
* zero after reverting the changeset, even if a subsequent error occurs.
*/
int of_overlay_remove(int *ovcs_id)
@ -1264,7 +1265,7 @@ EXPORT_SYMBOL_GPL(of_overlay_remove);
*
* Removes all overlays from the system in the correct order.
*
* Returns 0 on success, or a negative error number
* Return: 0 on success, or a negative error number
*/
int of_overlay_remove_all(void)
{

View File

@ -44,7 +44,7 @@ static const struct of_device_id of_skipped_node_table[] = {
* Takes a reference to the embedded struct device which needs to be dropped
* after use.
*
* Returns platform_device pointer, or NULL if not found
* Return: platform_device pointer, or NULL if not found
*/
struct platform_device *of_find_device_by_node(struct device_node *np)
{
@ -160,7 +160,7 @@ EXPORT_SYMBOL(of_device_alloc);
* @platform_data: pointer to populate platform_data pointer with
* @parent: Linux device model parent device.
*
* Returns pointer to created platform device, or NULL if a device was not
* Return: Pointer to created platform device, or NULL if a device was not
* registered. Unavailable devices will not get registered.
*/
static struct platform_device *of_platform_device_create_pdata(
@ -204,7 +204,7 @@ err_clear_flag:
* @bus_id: name to assign device
* @parent: Linux device model parent device.
*
* Returns pointer to created platform device, or NULL if a device was not
* Return: Pointer to created platform device, or NULL if a device was not
* registered. Unavailable devices will not get registered.
*/
struct platform_device *of_platform_device_create(struct device_node *np,
@ -290,7 +290,7 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
}
#endif /* CONFIG_ARM_AMBA */
/**
/*
* of_dev_lookup() - Given a device node, lookup the preferred Linux name
*/
static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *lookup,
@ -463,7 +463,7 @@ EXPORT_SYMBOL(of_platform_bus_probe);
* New board support should be using this function instead of
* of_platform_bus_probe().
*
* Returns 0 on success, < 0 on failure.
* Return: 0 on success, < 0 on failure.
*/
int of_platform_populate(struct device_node *root,
const struct of_device_id *matches,
@ -607,7 +607,7 @@ static void devm_of_platform_populate_release(struct device *dev, void *res)
* Similar to of_platform_populate(), but will automatically call
* of_platform_depopulate() when the device is unbound from the bus.
*
* Returns 0 on success, < 0 on failure.
* Return: 0 on success, < 0 on failure.
*/
int devm_of_platform_populate(struct device *dev)
{

View File

@ -61,9 +61,11 @@ EXPORT_SYMBOL(of_graph_is_present);
* @elem_size: size of the individual element
*
* Search for a property in a device node and count the number of elements of
* size elem_size in it. Returns number of elements on sucess, -EINVAL if the
* property does not exist or its length does not match a multiple of elem_size
* and -ENODATA if the property does not have a value.
* size elem_size in it.
*
* Return: The number of elements on sucess, -EINVAL if the property does not
* exist or its length does not match a multiple of elem_size and -ENODATA if
* the property does not have a value.
*/
int of_property_count_elems_of_size(const struct device_node *np,
const char *propname, int elem_size)
@ -95,8 +97,9 @@ EXPORT_SYMBOL_GPL(of_property_count_elems_of_size);
* @len: if !=NULL, actual length is written to here
*
* Search for a property in a device node and valid the requested size.
* Returns the property value on success, -EINVAL if the property does not
* exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
*
* Return: The property value on success, -EINVAL if the property does not
* exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
* property data is too small or too large.
*
*/
@ -129,7 +132,9 @@ static void *of_find_property_value_of_size(const struct device_node *np,
* @out_value: pointer to return value, modified only if no error.
*
* Search for a property in a device node and read nth 32-bit value from
* it. Returns 0 on success, -EINVAL if the property does not exist,
* it.
*
* Return: 0 on success, -EINVAL if the property does not exist,
* -ENODATA if property does not have a value, and -EOVERFLOW if the
* property data isn't large enough.
*
@ -161,7 +166,9 @@ EXPORT_SYMBOL_GPL(of_property_read_u32_index);
* @out_value: pointer to return value, modified only if no error.
*
* Search for a property in a device node and read nth 64-bit value from
* it. Returns 0 on success, -EINVAL if the property does not exist,
* it.
*
* Return: 0 on success, -EINVAL if the property does not exist,
* -ENODATA if property does not have a value, and -EOVERFLOW if the
* property data isn't large enough.
*
@ -196,12 +203,14 @@ EXPORT_SYMBOL_GPL(of_property_read_u64_index);
* sz_min will be read.
*
* Search for a property in a device node and read 8-bit value(s) from
* it. Returns number of elements read on success, -EINVAL if the property
* does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
* if the property data is smaller than sz_min or longer than sz_max.
* it.
*
* dts entry of array should be like:
* property = /bits/ 8 <0x50 0x60 0x70>;
* ``property = /bits/ 8 <0x50 0x60 0x70>;``
*
* Return: The number of elements read on success, -EINVAL if the property
* does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
* if the property data is smaller than sz_min or longer than sz_max.
*
* The out_values is modified only if a valid u8 value can be decoded.
*/
@ -244,12 +253,14 @@ EXPORT_SYMBOL_GPL(of_property_read_variable_u8_array);
* sz_min will be read.
*
* Search for a property in a device node and read 16-bit value(s) from
* it. Returns number of elements read on success, -EINVAL if the property
* does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
* if the property data is smaller than sz_min or longer than sz_max.
* it.
*
* dts entry of array should be like:
* property = /bits/ 16 <0x5000 0x6000 0x7000>;
* ``property = /bits/ 16 <0x5000 0x6000 0x7000>;``
*
* Return: The number of elements read on success, -EINVAL if the property
* does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
* if the property data is smaller than sz_min or longer than sz_max.
*
* The out_values is modified only if a valid u16 value can be decoded.
*/
@ -292,7 +303,9 @@ EXPORT_SYMBOL_GPL(of_property_read_variable_u16_array);
* sz_min will be read.
*
* Search for a property in a device node and read 32-bit value(s) from
* it. Returns number of elements read on success, -EINVAL if the property
* it.
*
* Return: The number of elements read on success, -EINVAL if the property
* does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
* if the property data is smaller than sz_min or longer than sz_max.
*
@ -331,7 +344,9 @@ EXPORT_SYMBOL_GPL(of_property_read_variable_u32_array);
* @out_value: pointer to return value, modified only if return value is 0.
*
* Search for a property in a device node and read a 64-bit value from
* it. Returns 0 on success, -EINVAL if the property does not exist,
* it.
*
* Return: 0 on success, -EINVAL if the property does not exist,
* -ENODATA if property does not have a value, and -EOVERFLOW if the
* property data isn't large enough.
*
@ -366,7 +381,9 @@ EXPORT_SYMBOL_GPL(of_property_read_u64);
* sz_min will be read.
*
* Search for a property in a device node and read 64-bit value(s) from
* it. Returns number of elements read on success, -EINVAL if the property
* it.
*
* Return: The number of elements read on success, -EINVAL if the property
* does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
* if the property data is smaller than sz_min or longer than sz_max.
*
@ -408,10 +425,11 @@ EXPORT_SYMBOL_GPL(of_property_read_variable_u64_array);
* return value is 0.
*
* Search for a property in a device tree node and retrieve a null
* terminated string value (pointer to data, not a copy). Returns 0 on
* success, -EINVAL if the property does not exist, -ENODATA if property
* does not have a value, and -EILSEQ if the string is not null-terminated
* within the length of the property data.
* terminated string value (pointer to data, not a copy).
*
* Return: 0 on success, -EINVAL if the property does not exist, -ENODATA if
* property does not have a value, and -EILSEQ if the string is not
* null-terminated within the length of the property data.
*
* The out_string pointer is modified only if a valid string can be decoded.
*/
@ -775,7 +793,7 @@ EXPORT_SYMBOL(of_graph_get_remote_port_parent);
* @node: pointer to a local endpoint device_node
*
* Return: Remote port node associated with remote endpoint node linked
* to @node. Use of_node_put() on it when done.
* to @node. Use of_node_put() on it when done.
*/
struct device_node *of_graph_get_remote_port(const struct device_node *node)
{
@ -808,7 +826,7 @@ EXPORT_SYMBOL(of_graph_get_endpoint_count);
* @endpoint: identifier (value of reg property) of the endpoint node
*
* Return: Remote device node associated with remote endpoint node linked
* to @node. Use of_node_put() on it when done.
* to @node. Use of_node_put() on it when done.
*/
struct device_node *of_graph_get_remote_node(const struct device_node *node,
u32 port, u32 endpoint)
@ -1230,7 +1248,7 @@ static struct device_node *parse_##fname(struct device_node *np, \
* @parse_prop.prop_name: Name of property holding a phandle value
* @parse_prop.index: For properties holding a list of phandles, this is the
* index into the list
* @optional: The property can be an optional dependency.
* @optional: Describes whether a supplier is mandatory or not
* @node_not_dev: The consumer node containing the property is never a device.
*
* Returns:
@ -1363,7 +1381,6 @@ static const struct supplier_bindings of_supplier_bindings[] = {
/**
* of_link_property - Create device links to suppliers listed in a property
* @dev: Consumer device
* @con_np: The consumer device tree node which contains the property
* @prop_name: Name of property to be parsed
*
@ -1387,7 +1404,6 @@ static int of_link_property(struct device_node *con_np, const char *prop_name)
const struct supplier_bindings *s = of_supplier_bindings;
unsigned int i = 0;
bool matched = false;
int ret = 0;
/* Do not stop at first failed link, link all available suppliers. */
while (!matched && s->parse_prop) {
@ -1410,7 +1426,7 @@ static int of_link_property(struct device_node *con_np, const char *prop_name)
}
s++;
}
return ret;
return 0;
}
static int of_fwnode_add_links(struct fwnode_handle *fwnode)

View File

@ -38,3 +38,51 @@ DTC_FLAGS_testcases += -@
# suppress warnings about intentional errors
DTC_FLAGS_testcases += -Wno-interrupts_property
# Apply overlays statically with fdtoverlay. This is a build time test that
# the overlays can be applied successfully by fdtoverlay. This does not
# guarantee that the overlays can be applied successfully at run time by
# unittest, but it provides a bit of build time test coverage for those
# who do not execute unittest.
#
# The overlays are applied on top of static_base_1.dtb and static_base_2.dtb to
# create static_test_1.dtb and static_test_2.dtb. If fdtoverlay detects an
# error than the kernel build will fail. static_test_1.dtb and
# static_test_2.dtb are not consumed by unittest.
#
# Some unittest overlays deliberately contain errors that unittest checks for.
# These overlays will cause fdtoverlay to fail, and are thus not included
# in the static test:
# overlay_bad_add_dup_node.dtbo \
# overlay_bad_add_dup_prop.dtbo \
# overlay_bad_phandle.dtbo \
# overlay_bad_symbol.dtbo \
apply_static_overlay_1 := overlay_0.dtbo \
overlay_1.dtbo \
overlay_2.dtbo \
overlay_3.dtbo \
overlay_4.dtbo \
overlay_5.dtbo \
overlay_6.dtbo \
overlay_7.dtbo \
overlay_8.dtbo \
overlay_9.dtbo \
overlay_10.dtbo \
overlay_11.dtbo \
overlay_12.dtbo \
overlay_13.dtbo \
overlay_15.dtbo \
overlay_gpio_01.dtbo \
overlay_gpio_02a.dtbo \
overlay_gpio_02b.dtbo \
overlay_gpio_03.dtbo \
overlay_gpio_04a.dtbo \
overlay_gpio_04b.dtbo
apply_static_overlay_2 := overlay.dtbo
static_test_1-dtbs := static_base_1.dtb $(apply_static_overlay_1)
static_test_2-dtbs := static_base_2.dtb $(apply_static_overlay_2)
dtb-$(CONFIG_OF_OVERLAY) += static_test_1.dtb static_test_2.dtb

View File

@ -2,92 +2,4 @@
/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";
rpm_avail = < 50 >;
};
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 {
#address-cells = <1>;
#size-cells = <1>;
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 >;
track@30 {
reg = < 0x00000030 0x10 >;
};
track@40 {
reg = < 0x00000040 0x10 >;
};
};
};
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";
};
};
};
#include "overlay_common.dtsi"

View File

@ -0,0 +1,91 @@
// SPDX-License-Identifier: GPL-2.0
/*
* 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";
rpm_avail = < 50 >;
};
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 {
#address-cells = <1>;
#size-cells = <1>;
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 >;
track@30 {
reg = < 0x00000030 0x10 >;
};
track@40 {
reg = < 0x00000040 0x10 >;
};
};
};
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";
};
};
};

View File

@ -0,0 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
#include "testcases_common.dtsi"

View File

@ -0,0 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
#include "overlay_common.dtsi"

View File

@ -2,19 +2,20 @@
/dts-v1/;
/plugin/;
#include "testcases_common.dtsi"
/ {
/*
* testcase data that intentionally results in an error is located here
* instead of in testcases_common.dtsi so that the static overlay apply
* tests will not include the error.
*/
testcase-data {
changeset {
prop-update = "hello";
prop-remove = "world";
node-remove {
};
testcase-device2 {
compatible = "testcase-device";
interrupt-parent = <&test_intc2>;
interrupts = <1>; /* invalid specifier - too short */
};
};
};
#include "tests-phandle.dtsi"
#include "tests-interrupts.dtsi"
#include "tests-match.dtsi"
#include "tests-address.dtsi"
#include "tests-platform.dtsi"
#include "tests-overlay.dtsi"

View File

@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-2.0
/ {
testcase-data {
changeset {
prop-update = "hello";
prop-remove = "world";
node-remove {
};
};
};
};
#include "tests-phandle.dtsi"
#include "tests-interrupts.dtsi"
#include "tests-match.dtsi"
#include "tests-address.dtsi"
#include "tests-platform.dtsi"
#include "tests-overlay.dtsi"

View File

@ -62,11 +62,10 @@
interrupts = <1>;
};
testcase-device2 {
compatible = "testcase-device";
interrupt-parent = <&test_intc2>;
interrupts = <1>; /* invalid specifier - too short */
};
/*
* testcase data that intentionally results in an error is
* located in testcases.dts instead of in this file so that the
* static overlay apply tests will not include the error.
*/
};
};

View File

@ -304,7 +304,15 @@ struct kimage {
#ifdef CONFIG_IMA_KEXEC
/* Virtual address of IMA measurement buffer for kexec syscall */
void *ima_buffer;
phys_addr_t ima_buffer_addr;
size_t ima_buffer_size;
#endif
/* Core ELF header buffer */
void *elf_headers;
unsigned long elf_headers_sz;
unsigned long elf_load_addr;
};
/* kexec interface functions */

View File

@ -424,12 +424,14 @@ extern int of_detach_node(struct device_node *);
* @sz: number of array elements to read
*
* Search for a property in a device node and read 8-bit value(s) from
* it. Returns 0 on success, -EINVAL if the property does not exist,
* -ENODATA if property does not have a value, and -EOVERFLOW if the
* property data isn't large enough.
* it.
*
* dts entry of array should be like:
* property = /bits/ 8 <0x50 0x60 0x70>;
* ``property = /bits/ 8 <0x50 0x60 0x70>;``
*
* Return: 0 on success, -EINVAL if the property does not exist,
* -ENODATA if property does not have a value, and -EOVERFLOW if the
* property data isn't large enough.
*
* The out_values is modified only if a valid u8 value can be decoded.
*/
@ -454,12 +456,14 @@ static inline int of_property_read_u8_array(const struct device_node *np,
* @sz: number of array elements to read
*
* Search for a property in a device node and read 16-bit value(s) from
* it. Returns 0 on success, -EINVAL if the property does not exist,
* -ENODATA if property does not have a value, and -EOVERFLOW if the
* property data isn't large enough.
* it.
*
* dts entry of array should be like:
* property = /bits/ 16 <0x5000 0x6000 0x7000>;
* ``property = /bits/ 16 <0x5000 0x6000 0x7000>;``
*
* Return: 0 on success, -EINVAL if the property does not exist,
* -ENODATA if property does not have a value, and -EOVERFLOW if the
* property data isn't large enough.
*
* The out_values is modified only if a valid u16 value can be decoded.
*/
@ -485,7 +489,9 @@ static inline int of_property_read_u16_array(const struct device_node *np,
* @sz: number of array elements to read
*
* Search for a property in a device node and read 32-bit value(s) from
* it. Returns 0 on success, -EINVAL if the property does not exist,
* it.
*
* Return: 0 on success, -EINVAL if the property does not exist,
* -ENODATA if property does not have a value, and -EOVERFLOW if the
* property data isn't large enough.
*
@ -513,7 +519,9 @@ static inline int of_property_read_u32_array(const struct device_node *np,
* @sz: number of array elements to read
*
* Search for a property in a device node and read 64-bit value(s) from
* it. Returns 0 on success, -EINVAL if the property does not exist,
* it.
*
* Return: 0 on success, -EINVAL if the property does not exist,
* -ENODATA if property does not have a value, and -EOVERFLOW if the
* property data isn't large enough.
*
@ -560,6 +568,13 @@ int of_map_id(struct device_node *np, u32 id,
phys_addr_t of_dma_get_max_cpu_address(struct device_node *np);
struct kimage;
void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
unsigned long initrd_load_addr,
unsigned long initrd_len,
const char *cmdline, size_t extra_fdt_size);
int ima_get_kexec_buffer(void **addr, size_t *size);
int ima_free_kexec_buffer(void);
#else /* CONFIG_OF */
static inline void of_core_init(void)
@ -1063,7 +1078,9 @@ static inline bool of_node_is_type(const struct device_node *np, const char *typ
* @propname: name of the property to be searched.
*
* Search for a property in a device node and count the number of u8 elements
* in it. Returns number of elements on sucess, -EINVAL if the property does
* in it.
*
* Return: The number of elements on sucess, -EINVAL if the property does
* not exist or its length does not match a multiple of u8 and -ENODATA if the
* property does not have a value.
*/
@ -1080,7 +1097,9 @@ static inline int of_property_count_u8_elems(const struct device_node *np,
* @propname: name of the property to be searched.
*
* Search for a property in a device node and count the number of u16 elements
* in it. Returns number of elements on sucess, -EINVAL if the property does
* in it.
*
* Return: The number of elements on sucess, -EINVAL if the property does
* not exist or its length does not match a multiple of u16 and -ENODATA if the
* property does not have a value.
*/
@ -1097,7 +1116,9 @@ static inline int of_property_count_u16_elems(const struct device_node *np,
* @propname: name of the property to be searched.
*
* Search for a property in a device node and count the number of u32 elements
* in it. Returns number of elements on sucess, -EINVAL if the property does
* in it.
*
* Return: The number of elements on sucess, -EINVAL if the property does
* not exist or its length does not match a multiple of u32 and -ENODATA if the
* property does not have a value.
*/
@ -1114,7 +1135,9 @@ static inline int of_property_count_u32_elems(const struct device_node *np,
* @propname: name of the property to be searched.
*
* Search for a property in a device node and count the number of u64 elements
* in it. Returns number of elements on sucess, -EINVAL if the property does
* in it.
*
* Return: The number of elements on sucess, -EINVAL if the property does
* not exist or its length does not match a multiple of u64 and -ENODATA if the
* property does not have a value.
*/
@ -1135,7 +1158,7 @@ static inline int of_property_count_u64_elems(const struct device_node *np,
* Search for a property in a device tree node and retrieve a list of
* terminated string values (pointer to data, not a copy) in that property.
*
* If @out_strs is NULL, the number of strings in the property is returned.
* Return: If @out_strs is NULL, the number of strings in the property is returned.
*/
static inline int of_property_read_string_array(const struct device_node *np,
const char *propname, const char **out_strs,
@ -1151,10 +1174,11 @@ static inline int of_property_read_string_array(const struct device_node *np,
* @propname: name of the property to be searched.
*
* Search for a property in a device tree node and retrieve the number of null
* terminated string contain in it. Returns the number of strings on
* success, -EINVAL if the property does not exist, -ENODATA if property
* does not have a value, and -EILSEQ if the string is not null-terminated
* within the length of the property data.
* terminated string contain in it.
*
* Return: The number of strings on success, -EINVAL if the property does not
* exist, -ENODATA if property does not have a value, and -EILSEQ if the string
* is not null-terminated within the length of the property data.
*/
static inline int of_property_count_strings(const struct device_node *np,
const char *propname)
@ -1168,13 +1192,14 @@ static inline int of_property_count_strings(const struct device_node *np,
* @np: device node from which the property value is to be read.
* @propname: name of the property to be searched.
* @index: index of the string in the list of strings
* @out_string: pointer to null terminated return string, modified only if
* @output: pointer to null terminated return string, modified only if
* return value is 0.
*
* Search for a property in a device tree node and retrieve a null
* terminated string value (pointer to data, not a copy) in the list of strings
* contained in that property.
* Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if
*
* Return: 0 on success, -EINVAL if the property does not exist, -ENODATA if
* property does not have a value, and -EILSEQ if the string is not
* null-terminated within the length of the property data.
*
@ -1194,7 +1219,8 @@ static inline int of_property_read_string_index(const struct device_node *np,
* @propname: name of the property to be searched.
*
* Search for a property in a device node.
* Returns true if the property exists false otherwise.
*
* Return: true if the property exists false otherwise.
*/
static inline bool of_property_read_bool(const struct device_node *np,
const char *propname)
@ -1440,14 +1466,14 @@ static inline int of_reconfig_get_state_change(unsigned long action,
* of_device_is_system_power_controller - Tells if system-power-controller is found for device_node
* @np: Pointer to the given device_node
*
* return true if present false otherwise
* Return: true if present false otherwise
*/
static inline bool of_device_is_system_power_controller(const struct device_node *np)
{
return of_property_read_bool(np, "system-power-controller");
}
/**
/*
* Overlay support
*/

View File

@ -73,14 +73,26 @@ always-y += $(userprogs-always-y) $(userprogs-always-m)
# DTB
# If CONFIG_OF_ALL_DTBS is enabled, all DT blobs are built
dtb-$(CONFIG_OF_ALL_DTBS) += $(dtb-)
# List all dtbs to be generated by fdtoverlay
overlay-y := $(foreach m,$(dtb-y), $(if $(strip $($(m:.dtb=-dtbs))),$(m),))
# Generate symbols for the base files so overlays can be applied to them.
$(foreach m,$(overlay-y), $(eval DTC_FLAGS_$(basename $(firstword $($(m:.dtb=-dtbs)))) += -@))
# Add base dtb and overlay dtbo
dtb-y += $(foreach m,$(overlay-y), $($(m:.dtb=-dtbs)))
always-y += $(dtb-y)
always-$(CONFIG_OF_ALL_DTBS) += $(dtb-)
ifneq ($(CHECK_DTBS),)
always-y += $(patsubst %.dtb,%.dt.yaml, $(dtb-y))
always-y += $(patsubst %.dtbo,%.dt.yaml, $(dtb-y))
always-$(CONFIG_OF_ALL_DTBS) += $(patsubst %.dtb,%.dt.yaml, $(dtb-))
always-$(CONFIG_OF_ALL_DTBS) += $(patsubst %.dtbo,%.dt.yaml, $(dtb-))
# Don't run schema checks for dtbs created by fdtoverlay as they don't
# have corresponding dts files.
dt-yaml-y := $(filter-out $(overlay-y),$(dtb-y))
always-y += $(patsubst %.dtb,%.dt.yaml, $(dt-yaml-y))
always-y += $(patsubst %.dtbo,%.dt.yaml, $(dt-yaml-y))
endif
# Add subdir path
@ -338,13 +350,23 @@ $(obj)/%.dtb: $(src)/%.dts $(DTC) FORCE
$(obj)/%.dtbo: $(src)/%.dts $(DTC) FORCE
$(call if_changed_dep,dtc)
overlay-y := $(addprefix $(obj)/, $(overlay-y))
quiet_cmd_fdtoverlay = DTOVL $@
cmd_fdtoverlay = $(objtree)/scripts/dtc/fdtoverlay -o $@ -i $(real-prereqs)
$(overlay-y): FORCE
$(call if_changed,fdtoverlay)
$(call multi_depend, $(overlay-y), .dtb, -dtbs)
DT_CHECKER ?= dt-validate
DT_CHECKER_FLAGS ?= $(if $(DT_SCHEMA_FILES),,-m)
DT_BINDING_DIR := Documentation/devicetree/bindings
# DT_TMP_SCHEMA may be overridden from Documentation/devicetree/bindings/Makefile
DT_TMP_SCHEMA ?= $(objtree)/$(DT_BINDING_DIR)/processed-schema.json
quiet_cmd_dtb_check = CHECK $@
cmd_dtb_check = $(DT_CHECKER) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@
cmd_dtb_check = $(DT_CHECKER) $(DT_CHECKER_FLAGS) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@
define rule_dtc
$(call cmd_and_fixdep,dtc)

View File

@ -3245,7 +3245,7 @@ sub process {
($line =~ /^new file mode\s*\d+\s*$/) &&
($realfile =~ m@^Documentation/devicetree/bindings/.*\.txt$@)) {
WARN("DT_SCHEMA_BINDING_PATCH",
"DT bindings should be in DT schema format. See: Documentation/devicetree/writing-schema.rst\n");
"DT bindings should be in DT schema format. See: Documentation/devicetree/bindings/writing-schema.rst\n");
}
# Check for wrappage within a valid hunk of the file

Some files were not shown because too many files have changed in this diff Show More