In-Band Firmware Update

Patrick Venture venture at google.com
Wed Aug 8 01:14:46 AEST 2018


On Mon, Aug 6, 2018 at 4:04 PM, Andrew Jeffery <andrew at aj.id.au> wrote:
>> I'd be interested in separating out the "file like" nature from the
>> interface, and keep it as just a "block level" update, that may be a
>> file, or may be something else.
>>
>
> A slight tangent, but I think it's worth talking about here:
>
> On OpenPOWER systems we developed a control protocol for the
> host to manipulate the LPC FW mapping. v3 of the protocol included
> support for mapping "arbitrary" stuff into the FW space with a
> command to list what devices were available. It seems very similar to
> what Patrick has outlined, though operates at the block level as Ed
> mused about above.

i'm somewhat familiar with the mailbox daemon and v3 protocols
insomuch as we were using them on our openpower system before
transitioning to phosphor-ipmi-flash (for consistency across
platform).

>
> Typically this mechanism is used for the host to access its firmware
> which - again on OpenPOWER designs - sits on a flash device owned
> by the BMC.
>
> The control protocol was run over the LPC mailbox available on
> ASPEED BMCs. However, I am currently developing a PoC IPMI
> replacement for the mailbox interface, and intended to use much
> the same command-set and argument layout as we have with the
> mailbox. As mentioned above it aligns pretty well with what Patrick
> is proposing.
>
> So our use-case has less of an update focus, but at the end of the
> day if you can perform arbitrary writes it roughly amounts to the
> same thing. Should we expand the scope to cover my use-case here?
> I'm fine if the answer is "no", but with the similarities it seemed
> necessary to bring up.

The explicit out-of-band-data flow-control messages in
phosphor-ipmi-flash fit the semantics to an extent.  We actually use
one of the packets in the design
https://github.com/openbmc/phosphor-ipmi-flash/blob/master/docs/flash_update.md#flashmapregionlpc-13
to provide information used for the ioctl:

bool LpcMapperAspeed::MapWindow(uint32_t *windowOffset, uint32_t *windowSize,
        uint32_t address, uint32_t length)
{
    static const uint32_t MASK_64K = 0xFFFFU;
    const uint32_t offset = address & MASK_64K;
    if (offset + length > regionSize)
    {
        fprintf(stderr, "requested window size %" PRIu32 ", offset %#" PRIx32
                " is too large for mem region at %#" PRIXPTR " of size %zu\n",
                length, offset, physAddr, regionSize);
        *windowSize = regionSize - offset;
        return false;
    }
    *windowOffset = offset;
    *windowSize = length;
    struct aspeed_lpc_ctrl_mapping map =
    {
        .window_type = ASPEED_LPC_CTRL_WINDOW_MEMORY,
        .window_id = 0,
        .flags = 0,
        .addr = address & ~MASK_64K,
        .offset = 0,
        .size = __ALIGN_KERNEL_MASK(offset + length, MASK_64K),
    };
    printf("requesting Aspeed LPC window at %#" PRIx32 " of size %" PRIu32 "\n",
           map.addr, map.size);
    static const char lpcControlPath[] = "/dev/aspeed-lpc-ctrl";
    const auto lpcControlFd = open(lpcControlPath, O_RDWR);
    if (FileClosed == lpcControlFd)
    {
        fprintf(stderr, "cannot open Aspeed LPC kernel control dev \"%s\"\n",
                lpcControlPath);
        return false;
    }
    if (ioctl(lpcControlFd, ASPEED_LPC_CTRL_IOCTL_MAP, &map) == -1)
    {
        fprintf(stderr, "Failed to ioctl Aspeed LPC map with error %s\n",
                strerror(errno));
        return false;
    }
    return true;
}

The above code is going into phosphor-ipmi-flash once I finish
rewriting the IPMI BT interface support.

>
> Cheers,
>
> Andrew
>
> PS: The bits -
> Repository: https://github.com/openbmc/mboxbridge
> Protocol documentation: https://github.com/openbmc/mboxbridge/blob/master/Documentation/mbox_protocol.md
> Implementation notes: https://github.com/openbmc/mboxbridge/blob/master/Documentation/mboxd.md


More information about the openbmc mailing list