I read this over myself and it looks good to me. What I am not sure I 
understood, and still not sure I do, is the sectors where these MMR will go. 
Are these going to go into some write protected location? Or will they just so 
somewhere that does not get erased when we do image upgrades? Not sure I need 
to understand either :-) 

> On Dec 11, 2018, at 3:43 AM, Łukasz Rymanowski 
> <lukasz.rymanow...@codecoup.pl> wrote:
> 
> Hi Chris,
> 
> I read it all and indeed it was thrilling :)
> 
> I think this is a good idea and this is a way to go. I have just feeling
> that internal mfgimage should be able to verify external one somehow, to
> make sure second factory did a good job
> But maybe this is not needed as  bootloader will do signature validation of
> the images inside the external mfgimage (if I recall correctly). Anyway,
> just a thought to consider.
> 
> Best
> Łukasz
> 
> On Tue, 11 Dec 2018 at 00:14, Christopher Collins <ch...@runtime.io> wrote:
> 
>> Hello all,
>> 
>> I've been reviewing Mynewt's manufacturing image (mfgimage) support.  I
>> think there are some shortcomings that we need to address.  I'll
>> attempt to explain the problems that I see and propose some fixes.
>> This is going to be a long email, so brace yourselves for a thrilling
>> read.
>> 
>> ### CURRENT IMPLEMENTATION
>> 
>> First, allow me to summarize what a Mynewt mfgimage is:
>> 
>> An mfgimage is the set of binaries that get written to a device at
>> manufacturing time.  Unlike a Mynewt target which corresponds to a
>> single executable image, an mfgimage represents the entire flash
>> contents.  Typically, an mfgimage consists of:
>> 
>>    * 1 boot loader.
>>    * 1 or 2 Mynewt images.
>>    * Extra configuration (e.g., a pre-populated sys/config region).
>> 
>> In addition, each mfgimage contains a manufacturing meta region (MMR).
>> The MMR consists of read-only data that resides in flash for the
>> lifetime of the device.  There is currently support for two MMR TLV
>> types:
>> 
>>    * Hash of mfgimage
>>    * Flash map
>> 
>> The manufacturing hash indicates which manufacuturing image a device
>> was built with.  A management system may need this information to
>> determine which images a device can be upgraded to, for example.  A
>> Mynewt device exposes its manufacturing hash via the `id/mfghash`
>> config setting.
>> 
>> Since the MMR is not intended to be modified or erased, it is placed in
>> an unmodifiable part of flash: the end of the boot loader area.
>> 
>> So far, it probably sounds like an mfgimage comprises only a single
>> binary file.  However, an mfgimage is actually a *set* of binaries -
>> one binary per flash component.  If a device has internal flash as well
>> as an external SPI flash, for example, then its mfgimage would consist
>> of two binary files.
>> 
>> An mfgimage is defined in an `mfg.yml` file.  Below is an example
>> `mfg.yml` file:
>> 
>>    # Sample `mfg.yml` file:
>>    mfg.bootloader: 'targets/boot-nrf52dk'
>> 
>>    mfg.images:
>>        - 'targets/slinky-nrf52dk'
>>        - 'targets/bleprph-nrf52dk'
>> 
>>    mfg.raw:
>>        - offset: 0x00080000
>>          file: mfgdata.raw
>> 
>>        - offset: 0x00090000
>>          file: file-system.raw
>> 
>> ### SHORTCOMINGS
>> 
>> The current mfgimage implementation makes a big assumption: all flash
>> components get programmed at the same time, more or less.  A single mfg
>> definition is used to create the full set of binaries.  It is not
>> possible to change only one binary in the set without creating an
>> entirely new mfgimage.
>> 
>> This assumption does not align with reality.  Often, the various flash
>> components are programmed by different parties without coordination.
>> For example, the internal flash is typically programmed by the MCU
>> vendor before the chips are shipped, while the external flash might be
>> programmed on the factory floor.  What if, during production, a defect
>> in the external flash contents is discovered?  Simply sending a patched
>> binary to the factory violates one of our requirements: we need to be
>> able to determine exactly how each device in the field was
>> manufactured.  Currently, the hash in a device's MMR tells us which
>> mfgimage it was built with, but the MMR is in the boot loader area in
>> internal flash, the part that the MCU vendor programs!  With the
>> current system, a new mfgimage needs to be created and built, the new
>> internal binary sent to the MCU vendor, and the new external binary
>> sent to the factory.  And this all needs to be done seamlessly - the
>> factory needs to switch to the new external binary only for MCUs
>> containing the new internal binary.  Suffice it to say, this is not a
>> practical solution.
>> 
>> What we really need is a way to update the external flash contents
>> without a corresponding change to the internal binary.  The MCU vendor
>> could continue flashing chips with the original binary they were
>> provided, and the factory could immediately switch over to their new
>> binary without needing to coordinate.  We need this to be possible
>> while sticking to one of our original requirements: it must be possible
>> to determine exactly how each device was programmed during
>> manufacturing.
>> 
>> ### PROPOSAL
>> 
>> # SUMMARY
>> 
>> The short version is:
>>    * An mfgimage spans one, and only one, flash component.
>>    * A device can be built with multipled mfgimages.
>>    * Each mfgimage has its own MMR.
>>    * A device's manufacturing identity (mfgid) is a *list* of all
>>      mfgimages the device was built with.
>> 
>> In the example above, there would be two mfgimages: "internal", and
>> "external".  The internal binary would be sent to the MCU vendor; the
>> external binary would be sent to the factory.  When a defect in the
>> external binary is discovered, a new external mfgimage would be
>> produced (with a new hash) and sent to the factory.  Devices
>> manufactured after this point would use the new external binary, and
>> continue to use the original internal binary.  Since a device's mfgid
>> is the full list of mfgimages it was built with, devices built after
>> the fix would be distinguishable from those affected by the defect.
>> 
>> # MFG HASH
>> 
>> Each mfgimage has its own MMR containing a hash.
>> 
>> The MMR at the end of the boot loader area (now called the "boot MMR")
>> must be present. The boot MMR indicates the flash locations of other
>> MMRs via the `mmr` TLV type.
>> 
>> At startup, the firmware reads the boot MMR (as before). Next, it reads
>> any additional MMRs indicated by `mmr` TLVs. An `mmr` TLV contains two
>> fields:
>> 
>>    * flash device ID
>>    * flash offset
>> 
>> The referenced MMR can be found at the specified location.
>> 
>> After all MMRs have been read, the firmware populates the `id/mfghash`
>> setting with a colon-separated list of hashes. By reading and parsing
>> this setting, a client can derive the full list of mfgimages that the
>> device was built with.
>> 
>> There are a few annoying implications:
>> 
>>    1. A flash sector for each extra MMR must be reserved in the BSP's
>>       flash map.
>>    2. The boot mfgimage has to know the location of the other MMRs.
>>       If an MMR is moved to a different flash offset, a new boot
>>       mfgimage with the updated offset must be built.
>> 
>> # SAMPLE `MFG.YML` FILES
>> 
>> Below are sample `mfg.yml` files for hypothetical "internal" and
>> "external" mfgimages.
>> 
>>    # internal/mfg.yml
>>    mfg.targets:
>>        # Include the boot loader only.
>>        -
>>            name: 'targets/boot-nrf52dk'
>>            area: FLASH_AREA_BOOTLOADER
>>            offset: 0
>> 
>>    mfg.meta:
>>        # The MMR is placed at the end of the boot loader area.
>>        area: FLASH_AREA_BOOTLOADER
>>        offset: end
>> 
>>        # Include a TLV containing the sha256 of the mfg image.
>>        hash: true
>> 
>>        # Point to MMRs of other mfgimage so that the firmware knows
>>        # where to find them.
>>        mmrs:
>>            -
>>                area: FLASH_AREA_EXT_MMR
>>                offset: 0
>> 
>> 
>>    # external/mfg.yml
>>    mfg.targets:
>>        # Include two images.
>>        -
>>            name: 'targets/slinky-nrf52dk'
>>            area: FLASH_AREA_IMAGE_0
>>            offset: 0
>>        -
>>            name: 'targets/bleprph-nrf52dk'
>>            area: FLASH_AREA_IMAGE_1
>>            offset: 0
>> 
>>    mfg.meta:
>>        # The MMR is placed at the start of the "external MMR" flash
>>        # area.
>>        area: FLASH_AREA_EXT_MMR
>>        offset: 0
>> 
>>        # Include a TLV containing the sha256 of the mfg image.
>>        hash: true
>> 
>>        # Include a flash map TLV.
>>        flash_map: true
>> 
>> All comments welcome.
>> 
>> Thanks,
>> Chris
>> 

Reply via email to