On Mon, Dec 30, 2019 at 3:49 PM Philippe Mathieu-Daudé <phi...@redhat.com>
wrote:

> On 12/18/19 9:49 PM, Niek Linnenbank wrote:
> > Hi Philippe,
> >
> > On Tue, Dec 17, 2019 at 8:45 AM Philippe Mathieu-Daudé
> > <phi...@redhat.com <mailto:phi...@redhat.com>> wrote:
> >
> >     Hi Niek,
> >
> >     On 12/17/19 12:35 AM, Niek Linnenbank wrote:
> >      > The Security Identifier device in Allwinner H3 System on Chip
> >      > gives applications a per-board unique identifier. This commit
> >      > adds support for the Allwinner H3 Security Identifier using
> >      > a 128-bit UUID value as input.
> >      >
> >      > Signed-off-by: Niek Linnenbank <nieklinnenb...@gmail.com
> >     <mailto:nieklinnenb...@gmail.com>>
> >      > ---
> >      >   include/hw/arm/allwinner-h3.h      |   2 +
> >      >   include/hw/misc/allwinner-h3-sid.h |  40 +++++++
> >      >   hw/arm/allwinner-h3.c              |   7 ++
> >      >   hw/arm/orangepi.c                  |   4 +
> >      >   hw/misc/allwinner-h3-sid.c         | 179
> >     +++++++++++++++++++++++++++++
> >      >   hw/misc/Makefile.objs              |   1 +
> >      >   hw/misc/trace-events               |   4 +
> >      >   7 files changed, 237 insertions(+)
> >      >   create mode 100644 include/hw/misc/allwinner-h3-sid.h
> >      >   create mode 100644 hw/misc/allwinner-h3-sid.c
> >      >
> >      > diff --git a/include/hw/arm/allwinner-h3.h
> >     b/include/hw/arm/allwinner-h3.h
> >      > index 8128ae6131..c98c1972a6 100644
> >      > --- a/include/hw/arm/allwinner-h3.h
> >      > +++ b/include/hw/arm/allwinner-h3.h
> >      > @@ -29,6 +29,7 @@
> >      >   #include "hw/misc/allwinner-h3-clk.h"
> >      >   #include "hw/misc/allwinner-h3-cpucfg.h"
> >      >   #include "hw/misc/allwinner-h3-syscon.h"
> >      > +#include "hw/misc/allwinner-h3-sid.h"
> >      >   #include "target/arm/cpu.h"
> >      >
> >      >   enum {
> >      > @@ -77,6 +78,7 @@ typedef struct AwH3State {
> >      >       AwH3ClockState ccu;
> >      >       AwH3CpuCfgState cpucfg;
> >      >       AwH3SysconState syscon;
> >      > +    AwH3SidState sid;
> >      >       GICState gic;
> >      >       MemoryRegion sram_a1;
> >      >       MemoryRegion sram_a2;
> >      > diff --git a/include/hw/misc/allwinner-h3-sid.h
> >     b/include/hw/misc/allwinner-h3-sid.h
> >      > new file mode 100644
> >      > index 0000000000..79c9a24459
> >      > --- /dev/null
> >      > +++ b/include/hw/misc/allwinner-h3-sid.h
> >      > @@ -0,0 +1,40 @@
> >      > +/*
> >      > + * Allwinner H3 Security ID emulation
> >      > + *
> >      > + * Copyright (C) 2019 Niek Linnenbank <nieklinnenb...@gmail.com
> >     <mailto:nieklinnenb...@gmail.com>>
> >      > + *
> >      > + * This program is free software: you can redistribute it and/or
> >     modify
> >      > + * it under the terms of the GNU General Public License as
> >     published by
> >      > + * the Free Software Foundation, either version 2 of the
> License, or
> >      > + * (at your option) any later version.
> >      > + *
> >      > + * This program is distributed in the hope that it will be
> useful,
> >      > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >      > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >      > + * GNU General Public License for more details.
> >      > + *
> >      > + * You should have received a copy of the GNU General Public
> License
> >      > + * along with this program.  If not, see
> >     <http://www.gnu.org/licenses/>.
> >      > + */
> >      > +
> >      > +#ifndef HW_MISC_ALLWINNER_H3_SID_H
> >      > +#define HW_MISC_ALLWINNER_H3_SID_H
> >      > +
> >      > +#include "hw/sysbus.h"
> >      > +#include "qemu/uuid.h"
> >      > +
> >      > +#define TYPE_AW_H3_SID    "allwinner-h3-sid"
> >      > +#define AW_H3_SID(obj)    OBJECT_CHECK(AwH3SidState, (obj),
> >     TYPE_AW_H3_SID)
> >      > +
> >      > +typedef struct AwH3SidState {
> >      > +    /*< private >*/
> >      > +    SysBusDevice parent_obj;
> >      > +    /*< public >*/
> >      > +
> >      > +    MemoryRegion iomem;
> >      > +    uint32_t control;
> >      > +    uint32_t rdkey;
> >      > +    QemuUUID identifier;
> >      > +} AwH3SidState;
> >      > +
> >      > +#endif
> >      > diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
> >      > index 1a9748ab2e..ba34f905cd 100644
> >      > --- a/hw/arm/allwinner-h3.c
> >      > +++ b/hw/arm/allwinner-h3.c
> >      > @@ -196,6 +196,9 @@ static void aw_h3_init(Object *obj)
> >      >
> >      >       sysbus_init_child_obj(obj, "cpucfg", &s->cpucfg,
> >     sizeof(s->cpucfg),
> >      >                             TYPE_AW_H3_CPUCFG);
> >      > +
> >      > +    sysbus_init_child_obj(obj, "sid", &s->sid, sizeof(s->sid),
> >      > +                          TYPE_AW_H3_SID);
> >
> >     Here add a property alias:
> >
> >              object_property_add_alias(obj, "identifier",
> OBJECT(&s->sid),
> >                                        "identifier", &error_abort);
> >
> >      >   }
> >      >
> >      >   static void aw_h3_realize(DeviceState *dev, Error **errp)
> >      > @@ -332,6 +335,10 @@ static void aw_h3_realize(DeviceState *dev,
> >     Error **errp)
> >      >       qdev_init_nofail(DEVICE(&s->cpucfg));
> >      >       sysbus_mmio_map(SYS_BUS_DEVICE(&s->cpucfg), 0,
> >     s->memmap[AW_H3_CPUCFG]);
> >      >
> >      > +    /* Security Identifier */
> >      > +    qdev_init_nofail(DEVICE(&s->sid));
> >      > +    sysbus_mmio_map(SYS_BUS_DEVICE(&s->sid), 0,
> >     s->memmap[AW_H3_SID]);
> >      > +
> >      >       /* Universal Serial Bus */
> >      >       sysbus_create_simple(TYPE_AW_H3_EHCI,
> s->memmap[AW_H3_EHCI0],
> >      >                            qdev_get_gpio_in(DEVICE(&s->gic),
> >      > diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
> >      > index 62cefc8c06..b01c4b4f01 100644
> >      > --- a/hw/arm/orangepi.c
> >      > +++ b/hw/arm/orangepi.c
> >      > @@ -62,6 +62,10 @@ static void orangepi_init(MachineState
> *machine)
> >      >           exit(1);
> >      >       }
> >      >
> >      > +    /* Setup SID properties */
> >      > +    qdev_prop_set_string(DEVICE(&s->h3->sid), "identifier",
> >      > +                         "8100c002-0001-0002-0003-000044556677");
> >
> >     And here use the alias:
> >
> >              qdev_prop_set_string(DEVICE(&s->h3), "identifier",
> >
>  "8100c002-0001-0002-0003-000044556677");
> >
> >
> > Ah OK, I see what you mean. The boards should be using the SoC object
> > only and
> > not directly any of its sub devices, correct?
> >
> >
> >     What means this value? Don't you want to be able to set it from
> command
> >     line?
> >
> > The first word 0x02c00081 is the identifying word for the H3 SoC in the
> > SID data.
> > After that come the per-device unique specific bytes. This is documented
> > at the end of this page in 'Currently known SID's' on the
> > linux-sunxi.org <http://linux-sunxi.org> Wiki:
> > https://linux-sunxi.org/SID_Register_Guide
> >
> > The remaining parts of this value I simply made up without any real
> meaning.
> > And yes, it would in fact make sense to have the user be able to
> > override it from the command line.
> > It is used by U-boot as an input for generating the MAC address. Linux
> > also reads it, but I did not investigate
> > how it us used there. I think I did make a TODO of using a cmdline
> > argument, but later forgot to actually implement it.
> >
> > Do you have a suggestion how to best provide the command line argument?
> > I do see '-device driver[,prop=value]'
> > is there in the --help for qemu-system-arm, but it looks like that
> > should be used by the user for adding PCI / USB devices?
>
> Look for '-global' in the manpage:
>
>
>    -global driver.prop=value
>    -global driver=driver,property=property,value=value
>
>      Set default value of driver's property prop to value.
>
>      In particular, you can use this to set driver properties
>      for devices which are created automatically by the machine
>      model. To create a device which is not created automatically
>      and set properties on it, use -device.
>
>      -global driver.prop=value is shorthand for
>      -global driver=driver,property=prop,value=value.
>
> So this should work for your device:
>
>      -global
> allwinner-h3-sid.identifier=8100c002-0001-0002-0003-000044556677
>

Thanks, I tried this, however currently its not applied when used.
I think its because the orangepi.c file sets the property as well.

Its not a blocking problem if the user can't override the SID value, but it
would be a nice-to-have.
U-Boot uses its value for MAC generation and that can be overridden as well
by U-Boot itself.



> >
> >
> >      >       /* Mark H3 object realized */
> >      >       object_property_set_bool(OBJECT(s->h3), true, "realized",
> >     &error_abort);
> >      >       if (error_abort != NULL) {
> >      > diff --git a/hw/misc/allwinner-h3-sid.c
> b/hw/misc/allwinner-h3-sid.c
> >      > new file mode 100644
> >      > index 0000000000..c472f2bcc6
> >      > --- /dev/null
> >      > +++ b/hw/misc/allwinner-h3-sid.c
> >      > @@ -0,0 +1,179 @@
> >      > +/*
> >      > + * Allwinner H3 Security ID emulation
> >      > + *
> >      > + * Copyright (C) 2019 Niek Linnenbank <nieklinnenb...@gmail.com
> >     <mailto:nieklinnenb...@gmail.com>>
> >      > + *
> >      > + * This program is free software: you can redistribute it and/or
> >     modify
> >      > + * it under the terms of the GNU General Public License as
> >     published by
> >      > + * the Free Software Foundation, either version 2 of the
> License, or
> >      > + * (at your option) any later version.
> >      > + *
> >      > + * This program is distributed in the hope that it will be
> useful,
> >      > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >      > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >      > + * GNU General Public License for more details.
> >      > + *
> >      > + * You should have received a copy of the GNU General Public
> License
> >      > + * along with this program.  If not, see
> >     <http://www.gnu.org/licenses/>.
> >      > + */
> >      > +
> >      > +#include "qemu/osdep.h"
> >      > +#include "qemu/units.h"
> >      > +#include "hw/sysbus.h"
> >      > +#include "migration/vmstate.h"
> >      > +#include "qemu/log.h"
> >      > +#include "qemu/module.h"
> >      > +#include "qemu/guest-random.h"
> >      > +#include "qapi/error.h"
> >      > +#include "hw/qdev-properties.h"
> >      > +#include "hw/misc/allwinner-h3-sid.h"
> >      > +#include "trace.h"
> >      > +
> >      > +/* SID register offsets */
> >      > +enum {
> >      > +    REG_PRCTL = 0x40,   /* Control */
> >      > +    REG_RDKEY = 0x60,   /* Read Key */
> >      > +};
> >      > +
> >      > +/* SID register flags */
> >      > +enum {
> >      > +    REG_PRCTL_WRITE   = 0x0002, /* Unknown write flag */
> >      > +    REG_PRCTL_OP_LOCK = 0xAC00, /* Lock operation */
> >      > +};
> >      > +
> >      > +static uint64_t allwinner_h3_sid_read(void *opaque, hwaddr
> offset,
> >      > +                                      unsigned size)
> >      > +{
> >      > +    const AwH3SidState *s = (AwH3SidState *)opaque;
> >      > +    uint64_t val = 0;
> >      > +
> >      > +    switch (offset) {
> >      > +    case REG_PRCTL:    /* Control */
> >      > +        val = s->control;
> >      > +        break;
> >      > +    case REG_RDKEY:    /* Read Key */
> >      > +        val = s->rdkey;
> >      > +        break;
> >      > +    default:
> >      > +        qemu_log_mask(LOG_GUEST_ERROR, "%s: bad read offset
> >     0x%04x\n",
> >      > +                      __func__, (uint32_t)offset);
> >      > +        return 0;
> >      > +    }
> >      > +
> >      > +    trace_allwinner_h3_sid_read(offset, val, size);
> >      > +
> >      > +    return val;
> >      > +}
> >      > +
> >      > +static void allwinner_h3_sid_write(void *opaque, hwaddr offset,
> >      > +                                   uint64_t val, unsigned size)
> >      > +{
> >      > +    AwH3SidState *s = (AwH3SidState *)opaque;
> >      > +
> >      > +    trace_allwinner_h3_sid_write(offset, val, size);
> >      > +
> >      > +    switch (offset) {
> >      > +    case REG_PRCTL:    /* Control */
> >      > +        s->control = val;
> >      > +
> >      > +        if ((s->control & REG_PRCTL_OP_LOCK) &&
> >      > +            (s->control & REG_PRCTL_WRITE)) {
> >      > +            uint32_t id = s->control >> 16;
> >      > +
> >      > +            if (id < sizeof(QemuUUID)) {
> >      > +                s->rdkey = (s->identifier.data[id]) |
> >      > +                           (s->identifier.data[id + 1] << 8) |
> >      > +                           (s->identifier.data[id + 2] << 16) |
> >      > +                           (s->identifier.data[id + 3] << 24);
> >
> >     This is:
> >
> >                          s->rdkey = ldl_le_p(&s->identifier.data[id]);
> >
> >      > +            }
> >      > +        }
> >      > +        s->control &= ~REG_PRCTL_WRITE;
> >      > +        break;
> >      > +    case REG_RDKEY:    /* Read Key */
> >
> >     Read in a write()?
> >
> >     Maybe we can simply /* fall through */ LOG_GUEST_ERROR?
> >
> >
> > When writing this module, I looked at how U-Boot is using the SID
> > registers and simply
> > named the registers after the names used by U-Boot. You can find this
> > part in arch/arm/mach-sunxi/cpu_info.c:111,
> > functions sun8i_efuse_read() and sunxi_get_sid(). U-Boot defines
> > SIDC_RDKEY, so I named the register also rdkey.
> > I used the U-Boot source because the Allwinner H3 datasheet does not
> > document the registers. Later I
> > found the SID page on the linux-sunxi wiki that I mentioned earlier, and
> > they also describe the same register names:
> >
> > https://linux-sunxi.org/SID_Register_Guide
>
> Hmm this page describe this register as RW, odd. I think this is wrong
> because we deal with a fuse, and we program it via the REG_PRKEY
> register. Does Linux/U-Boot do write access to this register?
> We can start logging LOG_GUEST_ERROR, and correct it if we notice this
> register is really writable (which I doubt).
>
>
Yes it seems so. The PRCTL is the "Control" register (R/W) and the RDKEY
the "Data" register (RO).
You can see the Linux implementation in drivers/nvmem/sunxi_sid.c
For U-Boot the file is in arch/arm/mach-sunxi/cpu_info.c, functions
sunxi_get_sid and sun8i_efuse_read.

Regards,
Niek


> >
> > I suspect the information on this page is written based on the source
> > code from the original SDK (which I did not study btw)
> [...]
>
>

-- 
Niek Linnenbank

Reply via email to