Esempio n. 1
0
async def microsd_upgrade(*a):
    # Upgrade vis MicroSD card
    # - search for a particular file
    # - verify it lightly
    # - erase serial flash
    # - copy it over (slow)
    # - reboot into bootloader, which finishes install

    fn = await file_picker('Pick firmware image to use (.DFU)',
                           suffix='.dfu',
                           min_size=0x7800)

    if not fn: return

    failed = None

    with CardSlot() as card:
        with open(fn, 'rb') as fp:
            from main import sf, dis
            from files import dfu_parse
            from ustruct import unpack_from

            offset, size = dfu_parse(fp)

            # get a copy of special signed heaer at the end of the flash as well
            from sigheader import FW_HEADER_OFFSET, FW_HEADER_SIZE, FW_HEADER_MAGIC, FWH_PY_FORMAT
            hdr = bytearray(FW_HEADER_SIZE)
            fp.seek(offset + FW_HEADER_OFFSET)

            # basic checks only: for confused customers, not attackers.
            try:
                rv = fp.readinto(hdr)
                assert rv == FW_HEADER_SIZE

                magic_value, timestamp, version_string, pk, fw_size = \
                                unpack_from(FWH_PY_FORMAT, hdr)[0:5]
                assert magic_value == FW_HEADER_MAGIC
                assert fw_size == size

                # TODO: maybe show the version string? Warn them that downgrade doesn't work?

            except Exception as exc:
                failed = "Sorry! That does not look like a firmware " \
                            "file we would want to use.\n\n\n%s" % exc

            if not failed:

                # copy binary into serial flash
                fp.seek(offset)

                buf = bytearray(256)  # must be flash page size
                pos = 0
                dis.fullscreen("Loading...")
                while pos <= size + FW_HEADER_SIZE:
                    dis.progress_bar_show(pos / size)

                    if pos == size:
                        # save an extra copy of the header (also means we got done)
                        buf = hdr
                    else:
                        here = fp.readinto(buf)
                        if not here: break

                    if pos % 4096 == 0:
                        # erase here
                        sf.sector_erase(pos)
                        while sf.is_busy():
                            await sleep_ms(10)

                    sf.write(pos, buf)

                    # full page write: 0.6 to 3ms
                    while sf.is_busy():
                        await sleep_ms(1)

                    pos += here

    if failed:
        await ux_show_story(failed, title='Corrupt')
        return

    # continue process...
    import machine
    machine.reset()
Esempio n. 2
0
async def microsd_upgrade(*a):
    # Upgrade vis MicroSD card
    # - search for a particular file
    # - verify it lightly
    # - erase serial flash
    # - copy it over (slow)
    # - reboot into bootloader, which finishes install

    fn = await file_picker('Pick firmware image to use (.DFU)', suffix='.dfu', min_size=0x7800)

    if not fn: return

    failed = None

    with CardSlot() as card:
        with open(fn, 'rb') as fp:
            from main import sf, dis
            from files import dfu_parse
            from utils import check_firmware_hdr

            offset, size = dfu_parse(fp)

            # we also put a copy of special signed heaer at the end of the flash
            from sigheader import FW_HEADER_OFFSET, FW_HEADER_SIZE

            # read just the signature header
            hdr = bytearray(FW_HEADER_SIZE)
            fp.seek(offset + FW_HEADER_OFFSET)
            rv = fp.readinto(hdr)
            assert rv == FW_HEADER_SIZE

            # check header values
            failed = check_firmware_hdr(hdr, size)

            if not failed:
                patched = 0
            
                # copy binary into serial flash
                fp.seek(offset)

                buf = bytearray(256)        # must be flash page size
                pos = 0
                dis.fullscreen("Loading...")
                while pos <= size + FW_HEADER_SIZE:
                    dis.progress_bar_show(pos/size)

                    if pos == size:
                        # save an extra copy of the header (also means we got done)
                        buf = hdr
                        patched += 1
                    else:
                        here = fp.readinto(buf)
                        if not here: break

                    if pos == (FW_HEADER_OFFSET & ~255):
                        # update w/ our patched version of hdr
                        buf[128:FW_HEADER_SIZE+128] = hdr
                        patched += 1

                    if pos % 4096 == 0:
                        # erase here
                        sf.sector_erase(pos)
                        while sf.is_busy():
                            await sleep_ms(10)

                    sf.write(pos, buf)

                    # full page write: 0.6 to 3ms
                    while sf.is_busy():
                        await sleep_ms(1)

                    pos += here

                assert patched == 2

    if failed:
        await ux_show_story(failed, title='Sorry!')
        return

    # continue process...
    import machine
    machine.reset()