linux/drivers/char/tpm/eventlog/of.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright 2012 IBM Corporation
   4 *
   5 * Author: Ashley Lai <ashleydlai@gmail.com>
   6 *         Nayna Jain <nayna@linux.vnet.ibm.com>
   7 *
   8 * Maintained by: <tpmdd-devel@lists.sourceforge.net>
   9 *
  10 * Read the event log created by the firmware on PPC64
  11 */
  12
  13#include <linux/slab.h>
  14#include <linux/of.h>
  15#include <linux/tpm_eventlog.h>
  16
  17#include "../tpm.h"
  18#include "common.h"
  19
  20int tpm_read_log_of(struct tpm_chip *chip)
  21{
  22        struct device_node *np;
  23        const u32 *sizep;
  24        const u64 *basep;
  25        struct tpm_bios_log *log;
  26        u32 size;
  27        u64 base;
  28
  29        log = &chip->log;
  30        if (chip->dev.parent && chip->dev.parent->of_node)
  31                np = chip->dev.parent->of_node;
  32        else
  33                return -ENODEV;
  34
  35        if (of_property_read_bool(np, "powered-while-suspended"))
  36                chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED;
  37
  38        sizep = of_get_property(np, "linux,sml-size", NULL);
  39        basep = of_get_property(np, "linux,sml-base", NULL);
  40        if (sizep == NULL && basep == NULL)
  41                return -ENODEV;
  42        if (sizep == NULL || basep == NULL)
  43                return -EIO;
  44
  45        /*
  46         * For both vtpm/tpm, firmware has log addr and log size in big
  47         * endian format. But in case of vtpm, there is a method called
  48         * sml-handover which is run during kernel init even before
  49         * device tree is setup. This sml-handover function takes care
  50         * of endianness and writes to sml-base and sml-size in little
  51         * endian format. For this reason, vtpm doesn't need conversion
  52         * but physical tpm needs the conversion.
  53         */
  54        if (of_property_match_string(np, "compatible", "IBM,vtpm") < 0) {
  55                size = be32_to_cpup((__force __be32 *)sizep);
  56                base = be64_to_cpup((__force __be64 *)basep);
  57        } else {
  58                size = *sizep;
  59                base = *basep;
  60        }
  61
  62        if (size == 0) {
  63                dev_warn(&chip->dev, "%s: Event log area empty\n", __func__);
  64                return -EIO;
  65        }
  66
  67        log->bios_event_log = kmemdup(__va(base), size, GFP_KERNEL);
  68        if (!log->bios_event_log)
  69                return -ENOMEM;
  70
  71        log->bios_event_log_end = log->bios_event_log + size;
  72
  73        if (chip->flags & TPM_CHIP_FLAG_TPM2)
  74                return EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
  75        return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
  76}
  77