[PATCH] schemas: Add schema for firmware logs

Simon Glass sjg at chromium.org
Sat Feb 4 13:04:40 CET 2023


Hi Peter,

On Sat, 4 Feb 2023 at 02:36, Peter Robinson <pbrobinson at gmail.com> wrote:
>
> Hi Simon,
>
> Does it make sense to devise something that is compatible with the
> kernel's pstore [1] mechanism?

Possibly...can you please be a little more specific?

Regards,
Simon

>
> Peter
>
> [1] https://lwn.net/Articles/434821/
>
> On Sat, Feb 4, 2023 at 12:20 AM Simon Glass <sjg at chromium.org> wrote:
> >
> > A common way to detect problems in firmware is to collect logs from
> > the firmware, then pass them to the OS for storage and analysis.
> >
> > Logs can take the form of simple text output, or structured logs where the
> > filename and line number, etc. are provided. Timestamps can sometimes be
> > useful, too.
> >
> > Ideally the log can be displayed as simple ASCII without always needing
> > a special program to read it.
> >
> > The firmware consists of various boot phases, any of which can contribute
> > log information. It is assumed that these logs are not interleaved, i.e.
> > that the phases run one after the other.
> >
> > The final boot phase (before the OS) is responsible for collecting the
> > logs, e.g. from a Transfer List, and placing them in the devicetree.
> >
> > This binding collects the logs as individual log at n subnodes within a
> > /chosen/logs node.
> >
> > If firmware phases use the devicetree to pass logs between each other,
> > then the /chosen node should still be used. The /options node is not
> > supported. Subsequent phases must be sure to use the next numbered
> > log at n node.
> >
> > If the log data is sitting in memory somewhere, it is possible to point
> > to it, rather than copying the data into a property. For large logs this
> > may be more efficient. It must end with a NUL character, so the total
> > space for actual log data is one byte less than the allocated size.
> >
> > If something goes wrong and an incomplete log record is emitted, then the
> > next record may appear to be part of it, since there is no LF or ETX
> > character at the end of the previous record.
> >
> > The intent with this binding is to provide a Linux driver which can
> > provide access to the log data after booting is complete.
> >
> > Other things not considered:
> > - signalling overflow of a log buffer
> > - circular log buffers
> > - a single unified log buffer with inline ASCII characters to indicate the
> >   phase and project
> > - log records that contain multiple lines of text
> >
> > Signed-off-by: Simon Glass <sjg at chromium.org>
> > ---
> >
> >  dtschema/schemas/chosen.yaml |   3 +
> >  dtschema/schemas/log.yaml    | 176 +++++++++++++++++++++++++++++++++++
> >  dtschema/schemas/logs.yaml   |  30 ++++++
> >  test/logs.dts                |  47 ++++++++++
> >  4 files changed, 256 insertions(+)
> >  create mode 100644 dtschema/schemas/log.yaml
> >  create mode 100644 dtschema/schemas/logs.yaml
> >  create mode 100644 test/logs.dts
> >
> > diff --git a/dtschema/schemas/chosen.yaml b/dtschema/schemas/chosen.yaml
> > index 86194dd..46cc9fb 100644
> > --- a/dtschema/schemas/chosen.yaml
> > +++ b/dtschema/schemas/chosen.yaml
> > @@ -236,6 +236,9 @@ properties:
> >        system.
> >
> >  patternProperties:
> > +  '^logs$':
> > +    $ref: logs.yaml#
> > +
> >    "^framebuffer": true
> >
> >  additionalProperties: false
> > diff --git a/dtschema/schemas/log.yaml b/dtschema/schemas/log.yaml
> > new file mode 100644
> > index 0000000..5218234
> > --- /dev/null
> > +++ b/dtschema/schemas/log.yaml
> > @@ -0,0 +1,176 @@
> > +# SPDX-License-Identifier: BSD-2-Clause
> > +# Copyright 2023 Google LLC
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/log.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Log-output binding
> > +
> > +maintainers:
> > +  - Simon Glass <sjg at chromium.org>
> > +
> > +description:
> > +  This holds a log file or console dump created by a single phase of the boot.
> > +  It typically consists of plain ASCII text, but it is also possible to
> > +  add metadata like files and line numbers.
> > +
> > +  Each log node has a hex unit address which indicates the order of progress
> > +  through the boot phases. The first node must be log at 0, followed by
> > +  log at 1, etc.
> > +
> > +select: false
> > +
> > +properties:
> > +  reg:
> > +    description:
> > +      Defines a unique log ID for the log represented by the log node.
> > +
> > +  boot-phase:
> > +    $ref: types.yaml#/definitions/string
> > +    description: |
> > +      Indicates the phase of boot which produced this log:
> > +
> > +        - pre-sram: Before SRAM is available
> > +        - verify: Verification step, which decides which of the available images
> > +          should be run next
> > +        - pre-ram: Sets up SDRAM
> > +        - some-ram: After SDRAM is working but before all of it is available.
> > +          Some RAM is available but it is limited (e.g. it may be split into
> > +          two pieces by the location of the running program) because the
> > +          program code is not yet relocated out of the way.
> > +        - loader: OS loader, typically the final firmware step
> > +
> > +    pattern: "^pre-sram|verify|pre-ram|some-ram|loader$"
> > +
> > +  project:
> > +    $ref: types.yaml#/definitions/string
> > +    description:
> > +      Indicates the name of the project which produced this log
> > +
> > +    pattern: "^U-Boot|TF-A"
> > +
> > +  time-format:
> > +    $ref: types.yaml#/definitions/string
> > +    description: |
> > +      Indicates the time format used by the log. Options are:
> > +
> > +        usec - a integer number of microseconds since reset was released,
> > +               expressed in ASCII, e.g. "123"
> > +
> > +    pattern: "^usec$"
> > +
> > +  text-start:
> > +    oneOf:
> > +      - $ref: types.yaml#/definitions/uint32
> > +      - $ref: types.yaml#/definitions/uint64
> > +    description:
> > +      These properties hold the physical start and end address of the log text
> > +      if the 'text' property is not used.
> > +
> > +      Note that text-start is inclusive, but text-end is exclusive.
> > +
> > +      The text must be terminated with a NUL character.
> > +
> > +  text-end:
> > +    oneOf:
> > +      - $ref: types.yaml#/definitions/uint32
> > +      - $ref: types.yaml#/definitions/uint64
> > +    description:
> > +      These properties hold the physical start and end address of the log text
> > +      if the 'text' property is not used.
> > +
> > +      Note that text-start is inclusive, but text-end is exclusive.
> > +
> > +      The text must be terminated with a NUL character.
> > +
> > +  text:
> > +    $ref: types.yaml#/definitions/string
> > +    description: |
> > +      Contains the log text, if it is not referred to by text-start / text-end.
> > +
> > +      The format is ASCII with US and SOT used to indicate optional fields:
> > +
> > +        [timestamp<US>][level[:category[:filename[:line[:function]]]]]<SOT>]message[<LF>|<ETX>]
> > +
> > +      where:
> > +
> > +        timestamp is the timestamp, according to time-format
> > +
> > +        level is the single-digit log level:
> > +           0 - emergency (program is unstable)
> > +           1 - alert (action must be taken immediately)
> > +           2 - crit (critical conditions)
> > +           3 - err (error that prevents something from working
> > +           4 - warning (may prevent optimal operation)
> > +           5 - notice (normal but significant condition, printf())
> > +           6 - info (general information message)
> > +           7 - debug (basic debug-level message)
> > +           8 - debug content (debug message showing full message content)
> > +           9 - debug I/O (debug message showing hardware I/O access)
> > +
> > +        category is the category name which is project-dependent
> > +
> > +        filename is the relative filename (__FILE__ in C)
> > +
> > +        line is the line number starting from 1 (__LINE__ in C)
> > +
> > +        function is the function name (__func__ in C)
> > +
> > +        message is the message string, which may not contain control
> > +        characters (beyond those listed above) except for HT and LF. DEL and CR
> > +        are not permitted.
> > +
> > +      The timestamp is present only if US is in the string.
> > +
> > +      The fields before <SOT> are all optional, but must be listed in order.
> > +      To omit a field in the middle, use an empty string between two colons.
> > +      To omit a field at the end, just leave it out along with the colon before
> > +      it.
> > +
> > +      Typically LF is used as a line delimiter, but if a record does not
> > +      end with a newline, ETX can be used. This indicates that it is a new
> > +      log record but without a newline between them. Often (but not always)
> > +      the 'continuation' does not include the US and SOT information.
> > +
> > +      A log record without a LF or ETX terminator is considered invalid, even
> > +      if it is the final record.
> > +
> > +      Examples:
> > +
> > +         123<US>5:tpm:lib/tpm.c:334:tpm_init<SOT>TPM starting...<LF>
> > +         23<US>Hello<LF>
> > +         2:boot:lib/panic.c:84:panic<SOT>Memory training failed<LF>
> > +         7:mmc:::mmc_bind<SOT>Cannot create block device<LF>
> > +         Net:   eth0: host_lo, eth1: host_enp1s0<ETX>
> > +
> > +      ASCII characters:
> > +
> > +        SOT - 0x2  - indicates the start of the message. This is optional if
> > +                     the record has nothing but a message
> > +        ETX - 0x3  - indicates the end of a log record (without new line)
> > +        LF  - 0xa  - indicates the end of a log record (and new line)
> > +        US  - 0x1f - indicates the end of the timestamp (and that it is present
> > +                     in the record)
> > +
> > +      The above format is intended to be unambiguous, while still being fairly
> > +      readable it just shown on a terminal with all control characters except
> > +      LF dropped. The CR character is not permitted since it is not needed to
> > +      signal an end of line and it avoids worrying about what <CR><LF> actually
> > +      means.
> > +
> > +      The text size is determined by the property size. The last byte must be
> > +      a NUL character.
> > +
> > +required:
> > +  - boot-phase
> > +  - project
> > +
> > +anyOf:
> > +  - required:
> > +    - text
> > +  - required:
> > +    - text-start
> > +    - text-end
> > +
> > +additionalProperties: false
> > diff --git a/dtschema/schemas/logs.yaml b/dtschema/schemas/logs.yaml
> > new file mode 100644
> > index 0000000..76ba2b0
> > --- /dev/null
> > +++ b/dtschema/schemas/logs.yaml
> > @@ -0,0 +1,30 @@
> > +# SPDX-License-Identifier: BSD-2-Clause
> > +# Copyright 2023 Google LLC
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/logs.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Log information collected during firmware execution
> > +
> > +maintainers:
> > +  - Simon Glass <sjg at chromium.org>
> > +
> > +description:
> > +  This holds a set of logs build up during booting of the machine. The
> > +  collection of logs is described in the "/logs" node.  This node in turn
> > +  contains a number of subnodes representing individual log output from
> > +  different boot phases.
> > +
> > +properties:
> > +  '#address-cells':
> > +    const: 1
> > +
> > +  '#size-cells':
> > +    const: 0
> > +
> > +patternProperties:
> > +  '^log@[0-9a-f]+$':
> > +    $ref: log.yaml#
> > +
> > +additionalProperties: false
> > diff --git a/test/logs.dts b/test/logs.dts
> > new file mode 100644
> > index 0000000..7d044df
> > --- /dev/null
> > +++ b/test/logs.dts
> > @@ -0,0 +1,47 @@
> > +// SPDX-License-Identifier: BSD-2-Clause
> > +// Copyright 2023 Google LLC
> > +
> > +// Used to validate the "logs" node and its child "log" nodes
> > +
> > +// dtc -O dtb -o test.dtb test/bootphases.dts && tools/dt-validate -s test/schemas -m test.dtb
> > +
> > +
> > +/dts-v1/;
> > +
> > +/ {
> > +       model = "none";
> > +       compatible = "foo";
> > +
> > +       #address-cells = <1>;
> > +       #size-cells = <1>;
> > +
> > +       chosen {
> > +               logs {
> > +                       #address-cells = <1>;
> > +                       #size-cells = <0>;
> > +
> > +                       log at 0 {
> > +                               reg = <0>;
> > +                               boot-phase = "pre-ram";
> > +                               project = "U-Boot";
> > +                               text = "\nU-Boot SPL 2023.01 (Feb 03 2023 - 14:45:39 -0700)\nTrying to boot from sandbox_image\nTrying to boot from sandbox_file\n";
> > +                       };
> > +
> > +                       log at 1 {
> > +                               reg = <1>;
> > +                               boot-phase = "loader";
> > +                               project = "U-Boot";
> > +                               time-format = "usec";
> > +                               text = "\n\n123\x1f2:boot:lib/display_options.c:43:display_options\x02U-Boot 2023.01 (Feb 03 2023 - 14:45:39 -0700)\n\nReset Status: COLD\nModel: sandbox\nDRAM:  256 MiB\n";
> > +                       };
> > +
> > +                       log at 2 {
> > +                               reg = <2>;
> > +                               boot-phase = "pre-ram";
> > +                               project = "TF-A";
> > +                               text-start = <0x103000>;
> > +                               text-end = <0x107000>;
> > +                       };
> > +               };
> > +       };
> > +};
> > --
> > 2.39.1.519.gcb327c4b5f-goog
> >


More information about the U-Boot mailing list