Coder Social home page Coder Social logo

uf2's Introduction

USB Flashing Format (UF2)

UF2 is a file format, developed by Microsoft for PXT (also known as Microsoft MakeCode), that is particularly suitable for flashing microcontrollers over MSC (Mass Storage Class; aka removable flash drive).

For a more friendly explanation, check out this blog post. Also, take a look at the list of implementations at the bottom of this document.

Overview

The UF2 file consists of 512 byte blocks, each of which is self-contained and independent of others. Each 512 byte block consists of (see below for details):

  • magic numbers at the beginning and at the end
  • address where the data should be flashed
  • up to 476 bytes of data

The data transfers over MSC always arrive in multiples of 512 bytes. Together with the FAT file system structure, this means that blocks of the UF2 file are always aligned with the MSC writes - the microcontroller never gets a partial file.

The magic numbers let the microcontroller distinguish an UF2 file block from other data (eg., FAT table entry, or various book-keeping files stored by some operating systems). When a UF2 block is recognized, it can be flashed immediately (unless flash page size is more than 256 bytes; in that case a buffer is needed). The actual handling of file format during writing is very simple (~10 lines of C code in simplest version).

File format

A UF2 file consists of 512 byte blocks. Each block starts with a 32 byte header, followed by data, and a final magic number. All fields, except for data, are 32 bit unsigned little endian integers.

Offset Size Value
0 4 First magic number, 0x0A324655 ("UF2\n")
4 4 Second magic number, 0x9E5D5157
8 4 Flags
12 4 Address in flash where the data should be written
16 4 Number of bytes used in data (often 256)
20 4 Sequential block number; starts at 0
24 4 Total number of blocks in file
28 4 File size or board family ID or zero
32 476 Data, padded with zeros
508 4 Final magic number, 0x0AB16F30

The following C struct can be used:

struct UF2_Block {
    // 32 byte header
    uint32_t magicStart0;
    uint32_t magicStart1;
    uint32_t flags;
    uint32_t targetAddr;
    uint32_t payloadSize;
    uint32_t blockNo;
    uint32_t numBlocks;
    uint32_t fileSize; // or familyID;
    uint8_t data[476];
    uint32_t magicEnd;
} UF2_Block;

Flags

Currently, there are five flags defined:

  • 0x00000001 - not main flash - this block should be skipped when writing the device flash; it can be used to store "comments" in the file, typically embedded source code or debug info that does not fit on the device flash
  • 0x00001000 - file container - see below
  • 0x00002000 - familyID present - when set, the fileSize/familyID holds a value identifying the board family (usually corresponds to an MCU)
  • 0x00004000 - MD5 checksum present - see below
  • 0x00008000 - extension tags present - see below

Family ID

This field is optional, and should be set only when the corresponding flag is set. It is recommended that new bootloaders require the field to be set appropriately, and refuse to flash UF2 files without it. If you're developing your own bootloader, and your board family isn't listed here, pick a new family ID at random. It's good to also send a PR here, so your family can be listed.

If the familyID doesn't match, the bootloader should disregard the entire block, including blockNo and numBlocks fields. In particular, writing a full UF2 file with non-matching familyID should not reset the board. This also allows for several files with different familyID to be simply concatenated together, and the whole resulting file to be copied to the device with only one actually being written to flash.

Picking numbers at random

The reason to pick numbers at random is to minimize risk of collisions in the wild. Do not pick random numbers by banging on keyboard, or by using 0xdeadf00d, 0x42424242 etc. A good way is to use the following shell command: printf "0x%04x%04x\n" $RANDOM $RANDOM Another good way is the link at the bottom of https://microsoft.github.io/uf2/patcher/ This procedure was unfortunately not used for the SAMD51 and NRF52840 below.

Family list

The current master list of family IDs is maintained in a JSON file.

Rationale

The magic number at the end is meant to mitigate partial block writes.

Second and final magic numbers were randomly selected, except for the last byte of final magic number, which was forced to be '\n' (0xA). Together with the first magic number being "UF2\n" this makes it easy to identify UF2 blocks in a text editor.

The header is padded to 32 bytes, as hex editors commonly use 16 or 32 bytes as line length. This way, the data payload is aligned to line start.

32 bit integers are used for all fields so that large flash sizes can be supported in future, as well as for simplicity. Little endian is used, as most microcontrollers are little endian. 8 bit microcontrollers can choose to just use the first 16 bits of various header fields.

The total number of blocks in the file and the sequential block number make it easy for the bootloader to detect that all blocks have been transferred. It requires one bit of memory per block (eg., on SAMD21G18A it's 128 bytes). Alternatively, the bootloader might ignore that and just implement a reset after say 1 second break in incoming UF2 blocks.

Payload sizes

The number of data bytes is configurable and depends on the size of the flash page (that is the smallest size that can be erased) on the microcontroller.

  • if the page size is more than 476 bytes, the bootloader should support any payload size, as it needs to buffer the entire page in memory anyway
  • if the page size is less than 476 bytes, the payload should be a multiple of page size, so it can be written without buffering; the target address should also be a multiple of page size

In any event, payload size and target address should always be 4-byte aligned.

Note that payload size of 256 is always correct, and makes it easy to convert between flash addresses and UF2 file offsets.

For example, on Atmel's SAMD21 chips the page size is 256 bytes, and this also is the payload size. If the page size was 128 bytes, one could use payload of 128*3. Nordic nRF51 has page size of 1024 bytes, and thus any payload size should be allowed.

Embedding sources

Some IDEs will embed program sources in the UF2 file. This allows a UF2 files to be loaded by the IDE and serve as a natural backup and transfer format. This can be done in two ways:

  • using the "not main flash" flag
  • using normal blocks that are flashed to the device

If the bootloader can expose CURRENT.UF2 file (see below) and there is enough flash available, than the second option is more desirable, as it allows sharing programs directly from the board.

See https://makecode.com/source-embedding for more info.

Robustness

The file format is designed specifically to deal with the following problems:

  • operating system (OS) writing blocks in different order than occurs in a file
  • OS writing blocks multiple times
  • OS writing data that is not UF2 blocks
  • OS writing first/final part of a block, possibly for metadata detection or search indexing

The only file system assumption we make is that blocks of file are aligned with blocks on the hard drive. It's likely true of many file systems besides FAT.

We also assume that USB MSC device reports its block size to be a multiple of 512 bytes. In the wild these devices always almost report exactly 512, and some operating systems do not support other values.

Files exposed by bootloaders

Bootloaders may expose virtual files in their MSC devices. These are standardized here, so that flashing tools can automatically detect the bootloaders.

  • INFO_UF2.TXT - contains information about the bootloader build and the board on which it is running
  • INDEX.HTM - redirects to a page that contains an IDE or other information
  • CURRENT.UF2 - the contents of the entire flash of the device, starting at 0x00000000, with 256 payload size; thus, the size of this file will report as twice the size of flash

Flashing tools can use the presence of INFO_UF2.TXT (in upper or lower case, as FAT is case-insensitive) file as an indication that a given directory is actually a connected UF2 board. The other files should not be used for detection.

Typical INFO_UF2.TXT file looks like this:

UF2 Bootloader v1.1.3 SFA
Model: Arduino Zero
Board-ID: SAMD21G18A-Zero-v0

The Board-ID field is machine-readable and consists of a number of dash-separated tokens. The first token is the CPU type, second is the board type, and third is the board revision. More tokens can be also added.

The bootloader should contain its info file as a static string somewhere in its code. If possible, the last word of the bootloader code should point to this string. This way, the info file can be found in the initial section of the CURRENT.UF2 file as well. Thus, a board type can be determined from the contents of CURRENT.UF2. This is particularly useful with the source embedding (see above).

File containers

It is also possible to use the UF2 format as a container for one or more regular files (akin to a TAR file, or ZIP archive without compression). This is useful when the embedded device being flashed sports a file system.

The program to run may reside in one of the files, or in the main flash memory.

In such a usage the file container flag is set on blocks, the field fileSize holds the file size of the current file, and the field targetAddr holds the offset in current file.

The not main flash flag on blocks should be ignored when the file container is set.

The file name is stored at &data[payloadSize] (ie., right after the actual payload) and terminated with a 0x00 byte. The format of filename is dependent on the bootloader (usually implemented as some sort of file system daemon).

The bootloader will usually allow any size of the payload.

The current files on device might be exposed as multiple UF2 files, instead of a single CURRENT.UF2. They may reside in directories, however, due to UF2 general design, it doesn't matter which directory the UF2 file is written to.

Typical writing procedure is as follows:

  • validate UF2 magic numbers
  • make sure that targetAddr < fileSize and that fileSize isn't out of reasonable range
  • write 0x00 at data[475] to ensure NUL termination of file name
  • read file name from &data[payloadSize]; perform any mapping on the file name
  • create a directory where the file is to be written if it doesn't exist
  • open the file for writing
  • truncate the file to fileSize
  • seek targetAddr
  • write the payload (ie., data[0 ... payloadSize - 1])
  • close the file

The fields blockNo and numBlocks refer to the entire UF2 file, not the current file.

MD5 checksum

When the 0x4000 flag is set, the last 24 bytes of data[] hold the following structure:

Offset Size Value
0 4 Start address of region
4 4 Length of region in bytes
8 16 MD5 checksum in binary format

The flashing program should compute the MD5 sum of the specified region. If the region checksum matches, flashing of the current block can be skipped. Typically, many blocks in sequence will have the same region specified, and can all be skipped, if the matching succeeded. The position of the current block will typically be inside of the region. The position and size of the region should be multiple of page erase size (4k or 64k on typical SPI flash).

This is currently only used on ESP32, which is also why MD5 checksum is used.

Extension tags

When the 0x8000 flag is set, additional information can be appended right after payload data (i.e., it starts at 32 + payloadSize). Every tag starts at 4 byte boundary. The first byte of tag contains its total size in bytes (including the size byte and type designation). The next three bytes designate the type of tag (if you want to define custom tags, pick them at random). The last tag has size of 0 and type of 0.

Standard tag designations follow:

  • 0x9fc7bc - version of firmware file - UTF8 semver string
  • 0x650d9d - description of device for which the firmware file is destined (UTF8)
  • 0x0be9f7 - page size of target device (32 bit unsigned number)
  • 0xb46db0 - SHA-2 checksum of firmware (can be of various size)
  • 0xc8a729 - device type identifier - a refinement of familyID meant to identify a kind of device (eg., a toaster with specific pinout and heating unit), not only MCU; 32 or 64 bit number; can be hash of 0x650d9d

For example, the following bytes encode firmware version 0.1.2 for device named ACME Toaster mk3 (line breaks added for clarity):

09 bc c7 9f 30 2e 31 2e 32 00 00 00
14 9d 0d 65 41 43 4d 45 20 54 6f 61 73 74 65 72 20 6d 6b 33
00 00 00 00

Extension tags can, but don't have to, be repeated in all blocks.

Implementations

Bootloaders

There's an ongoing effort to implement UF2 in Codal.

Editors

Libraries

License

MIT

Code of Conduct

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

uf2's People

Contributors

abchatra avatar bcr avatar benclifford avatar charkster avatar crazor avatar dhalbert avatar dobairoland avatar hathach avatar henrygab avatar horrortroll avatar icarus113 avatar jepler avatar johnazoidberg avatar k0d avatar karlk90 avatar kjsdf7wr3 avatar litui avatar lurch avatar mmoskal avatar ntoll avatar pabigot avatar pelikhan avatar peterdragun avatar pierstitus avatar shlomozippel avatar taorye avatar tballmsft avatar whitequark avatar wren6991 avatar zvecr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

uf2's Issues

HEX file accepted as input

Hi,

With the uf2conv.py tool, it states it can only be used with bin files, yet hex files are accepted. Rejection of hex files would be a nice feature, as it builds incompatible uf2 files.

feature request: allow file downloads

I have a use case where I would like to download a file from a UF2 enabled board. The use case involves logging data to memory of a board (MCU flash, SPI nor or nand flash, etc) and facilitating a way for the end user to easily download the data from the device. Thus, I was curious if any thought had been given to providing a mechanism where data moves from the board to the host? For instance, a "file" appears in the UF2 volume that could be copied to the host? For instance, when the copy begins, UF2 uses some sort of file system or application API to retrieve the data from the board memory.

Integrity check for firmware

Hi,

I think it would be good to be able to check the integrity of the firmware to be flashed / is already flashed. Currently there is no checksum included in the UF2 structure.

Readme - Extensions tags example

The section states that the type of tag for "description of device" is 0x650d9d In the example it is used but there(second line) it reads: "14 9d 9d 65 ".

So either the tag type is 0x659d9d or the example should be 14 9d 0d 65....

Or did I miss understand something here?

uf2tool portability issues

I don't see what platforms uf2tool builds for but it looks specifically written for osx and won't build on linux. This should probably be noted in the README.

[tom@z400 uf2tool]$ make
mkdir -p ../built
cc -g -Wall tool.c ../hidapi/mac/hid.c -I../../uf2-samd21/inc -I../hidapi/hidapi -I. -framework IOKit -framework CoreFoundation -o ../built/uf2tool
cc: error: IOKit: No such file or directory
cc: error: CoreFoundation: No such file or directory
cc: error: unrecognized command line option '-framework'
cc: error: unrecognized command line option '-framework'
make: *** [Makefile:3: all] Error 1
[tom@z400 uf2tool]$

I tried tidying the Makefile but the hidapi seems also to be reverting to osx.
.
.
../hidapi/mac/hid.c:25:36: fatal error: IOKit/hid/IOHIDManager.h: No such file or directory
#include <IOKit/hid/IOHIDManager.h>

I am running archlinux.

[tom@z400 uf2tool]$ uname -a
Linux z400 4.10.10-1-ARCH #1 SMP PREEMPT Wed Apr 12 18:50:28 CEST 2017 x86_64 GNU/Linux

edit
This line builds ok for linux.

$(CC) -g -Wall tool.c ../hidapi/linux/hid.c -I../../uf2-samd21/inc -I../hidapi/hidapi -ludev -lpthread -o ../built/uf2tool

Can a UF2 file only have one family ID?

Is it possible to concatenate multiple UF2 files which have different family IDs? If all the flags were 0x2000 shouldn't that allow the single UF2 file to be programmed correctly on different mcu architectures? I am wanting to create complex valid UF2 files for testing #48 feature in uf2conv.py . I did not properly handle multiple family IDs in pull request #49 .
If multiple family IDs are allowed, how can I create UF2 files properly? Do the magic numbers need to be different before the files are concatenated?
Thanks.

Need input file

Need input file i got this error idk what it is please help

could not open uf2 file

im trying to open this uf2 file with 'makecode.adafruit.com' but it keep saying "we could not recognize this file" for some reason

1
2
3

any help ?

Can we separate the family ID values into a single source of truth

'SAMD21': 0x68ed2b88,

I imagine things will get out of hand with naming and numbering conventions for the family IDs. I recommend that we have a single location for all of the family IDs (a JSON file perhaps), and some discipline around naming.

Even between the uf2conv.py script and the README.md for this repo, we're already starting to see some differences (in my example, Microchip (Atmel) SAMD21 vs. SAMD21)

This is going to get even harder when we start trying to be smarter about which family ID matches which board ID. In the example given in the README:

Board-ID: SAMD21G18A-Zero-v0

Which family ID will match that? Do we have to create an additional registry that maps between board IDs and family IDs?

Please define HF2 interface identification rules

For HF2 you don't specify any method of recognizing an HID interface as providing HF2.

I suggest two possible methods:

  1. Interface name containing "HF2".
  2. Declare a HID usage page for HF2.

Ideally both would be required in an implementation, letting the host use whichever is easiest and/or supported by the USB library being used.

Granularity of device ids

Hi,
what is the granularity of the device ids?
Should every chip with a different flash size get its own device id?
E.g. there are 6 different versions of the STM32F407 with different flash sizes and different amount of pins.

Make uf2conv.py available via pip

By having this available via pip it makes it easier for people to use this in other projects and keep track as updates are made to support additional boards and such.

cannot make uf2

The following error message was output

Traceback (most recent call last):
  File "uf2/utils/uf2conv.py", line 314, in <module>
    main()
  File "uf2/utils/uf2conv.py", line 290, in main
    outbuf = convert_to_carray(inpbuf)
  File "uf2/utils/uf2conv.py", line 99, in convert_to_carray
    outp += "0x%02x, " % file_content[i]
TypeError: %x format: a number is required, not str

I think it's due to the last changes.
41394bd

Support for nRF52832

Is there any change to support the nRF52832 SoC? If not, if it's doable, what would be the high level work items to accomplish it?

Thanks,

JavaScript implementation for UF2

Hi, I have created a JavaScript library to read/write the UF2 format:

https://www.npmjs.com/package/uf2

It exports a function that can decode a UF2 block (given as a byte array), and another function that encodes a block.

For instance, the following Node.js code loads blink.uf2 and prints the list of blocks in that files:

const fs = require('fs');
const { decodeBlock, familyMap } = require('uf2');

const file = fs.openSync('blink.uf2');
const buffer = new Uint8Array(512);
while (fs.readSync(file, buffer) === buffer.length) {
  const block = decodeBlock(buffer);
  const family = familyMap.get(block.boardFamily) || 'unknown';
  const { totalBlocks, blockNumber, flashAddress, payload } = block;
  const hexAddress = '0x' + flashAddress.toString(16);
  console.log(`Block ${blockNumber + 1}/${totalBlocks} @${hexAddress}, Family: ${family}`);
  // Do something with payload...
}
fs.closeSync(file);

Sample output:

Block 1/50 @0x10000000, Family: Raspberry Pi RP2040
Block 2/50 @0x10000100, Family: Raspberry Pi RP2040
Block 3/50 @0x10000200, Family: Raspberry Pi RP2040
Block 4/50 @0x10000300, Family: Raspberry Pi RP2040
Block 5/50 @0x10000400, Family: Raspberry Pi RP2040
...

Additional examples are available in the unit tests file.

I hope you'll find it useful, and thank you for creating this very useful firmware file format :-)

u-blox nina b4 running MicroCode

Hi There
I got success today to run Microsoft Microcode on NRF52833, using the Adafruit Bootloader :)
I have to edit the HEX code created my Microcode and convert it to uf2 using the uf2conv.py utililty.

Can someone help me to make a new uf2conv.py version, that

  • identify the Microcode hex,
  • then remove the extra hex
  • then finally convert to uf2

This is be interesting to the community

image

image

Miguel Wisintainer

No build description or instructions

Is this meant for Linux, Windows OSx?
How to build on Windows? Do you need to create some VS project, or do you have to
install make, mingw and or gccwin ?

Not clear at all, some of us are new to Github. A how-to one liner would help a lot.
Thank you.

Add displaying of block header when converting uf2 to bin (family_id, flags, target_address, payload, etc..)

Would it be possible to add the displaying of uf2 block header information when parsing a uf2 file? Additionally could there be a switch to just parse the provided uf2 file without conversion, in order to only display the block header information. If this is possible could the family_id short name also be displayed, otherwise I would still need to check the uf2families.json file.
uf2conv.py already parses uf2 files, so I was hoping this feature could be expanded.
Thanks.

speak will also be stuck

When I use stm32f411ce to install the simulator and run the arcade uF2 firmware, the sound will be stuck when playing, and adjusting the volume will also be stuck. My definition is as follows,

Likelihood of out of order block writes?

The robustness section of the project readme states that the file format is designed to handle an OS writing blocks out of order. I'm curious to know how common this is and what specific operating systems do this.

Ambiguity in uf2families.json for STM32F4 processors

The uf2families.json file contains multiple IDs relating to STM32F4 processors - 1 for the entire series and 2 relating to the STM32F407 product line within that series. However, the description for the entire series is ST STM32F401 which I believe is incorrect! This appears to have caused some confusion in two related open source projects where different IDs have been used for the STM32F405. I would like to propose changing the description to try and improve the situation.

   {
        "id": "0x57755a57",
        "short_name": "STM32F4",
        "description": "ST STM32F4xx"
    },

For reference:
https://www.st.com/content/ccc/fragment/product_related/series_information/series_level_diagram/group0/6e/ab/f8/ba/9c/9a/4d/37/obn_stm32f4_series_ss1577/files/obn_stm32f4_series_ss1577.jpg/jcr:content/translations/en.obn_stm32f4_series_ss1577.jpg

converting .bin file to .UF2

Forgive my confusion, but how does this whole thing work? UF2tool isn't a PC executable, it's a c file. I can't run c on a pc to convert a .bin file. Some directions would be greatly appreciated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.