Skip to content

Add uf2 combine command#313

Open
will-v-pi wants to merge 5 commits into
developfrom
uf2-combine
Open

Add uf2 combine command#313
will-v-pi wants to merge 5 commits into
developfrom
uf2-combine

Conversation

@will-v-pi
Copy link
Copy Markdown
Contributor

This combines 2 UF2s into 1, modifying the block numbers, and giving them same family ID, so it can be loaded as a single UF2 file. Can be called repeatedly to combine more UF2s.

Main use case is for combining partition tables with their partitions for loading as a single UF2 file. This will make running pico-examples that use partition tables easier, as a single UF2 can be generated for loading.

I think this was requested by @timg236, and it also fixes #169

will-v-pi added 4 commits May 6, 2026 14:30
Combines 2 UF2s into 1, modifying the block numbers (and giving them same family ID)
Allows placing second uf2 at offset, or in a partition defined in the first uf2
@will-v-pi will-v-pi added this to the 2.3.0 milestone May 14, 2026
@will-v-pi will-v-pi requested a review from kilograham May 14, 2026 16:12
Comment thread README.md
Comment thread README.md
Comment thread README.md
Comment thread README.md
Comment thread README.md
@lurch
Copy link
Copy Markdown
Contributor

lurch commented May 19, 2026

I think this was requested by @timg236, and it also fixes #169

I think @peterharperuk also said that it'd be nice if some of the pico-examples were also installable with a single UF2 file?

@lurch
Copy link
Copy Markdown
Contributor

lurch commented May 26, 2026

Could / should this PR also contain code to do raspberrypi/pico-examples#746 (comment) in order to remove the Unix-only limitation? Or is that outside the scope of what this PR is doing?

Comment thread main.cpp
).force_expand_help(true) % "UF2 Family options" +
(
option("--platform") & platform_model("platform").set(settings.model) % "optional platform for memory verification (eg rp2040, rp2350)"
option("--platform") % "Optional platform for memory verification" &
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does "memory verification" mean? Is it actually verifying the memory of the RP2350, or is it just checking that addresses are in the right ranges? If the latter, perhaps "Optional platform for memory-address validation" would be better? 🤷

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just checking that addresses are in the right ranges

Suggested change
option("--platform") % "Optional platform for memory verification" &
option("--platform") % "Optional platform for memory-address validation" &

Comment thread main.cpp
Comment thread main.cpp
}

bool uf2_combine_command::execute(device_map &devices) {
if (get_file_type_idx(0) != filetype::uf2 || get_file_type_idx(1) != filetype::uf2 || get_file_type_idx(0) != filetype::uf2) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (get_file_type_idx(0) != filetype::uf2 || get_file_type_idx(1) != filetype::uf2 || get_file_type_idx(0) != filetype::uf2) {
if (get_file_type_idx(0) != filetype::uf2 || get_file_type_idx(1) != filetype::uf2) {

Or do you just want to be extra sure that the first file is a UF2? 😆

Comment thread main.cpp
@will-v-pi
Copy link
Copy Markdown
Contributor Author

Could / should this PR also contain code to do raspberrypi/pico-examples#746 (comment) in order to remove the Unix-only limitation? Or is that outside the scope of what this PR is doing?

This is similar but separate, as they are different methods of combining UF2 files - that would be a separate uf2 concat command or similar, which would be outside the scope of this PR

@lurch
Copy link
Copy Markdown
Contributor

lurch commented May 26, 2026

Could / should this PR also contain code to do raspberrypi/pico-examples#746 (comment) in order to remove the Unix-only limitation? Or is that outside the scope of what this PR is doing?

This is similar but separate, as they are different methods of combining UF2 files - that would be a separate uf2 concat command or similar, which would be outside the scope of this PR

Hmm, so from my limited understanding of picotool and UF2 files, would the idea then be that uf2 combine is used to combine e.g. two RP2350 UF2s into a single larger UF2 (i.e. each block from the input UF2s gets written to a different flash address), but uf2 concat would be used two combine a RP2350 UF2 and a RP2040 UF2 into a single larger UF2 that could then be written to either board? (i.e. each block in the input UF2s might be targetting the same flash address)

@will-v-pi
Copy link
Copy Markdown
Contributor Author

Could / should this PR also contain code to do raspberrypi/pico-examples#746 (comment) in order to remove the Unix-only limitation? Or is that outside the scope of what this PR is doing?

This is similar but separate, as they are different methods of combining UF2 files - that would be a separate uf2 concat command or similar, which would be outside the scope of this PR

Hmm, so from my limited understanding of picotool and UF2 files, would the idea then be that uf2 combine is used to combine e.g. two RP2350 UF2s into a single larger UF2 (i.e. each block from the input UF2s gets written to a different flash address), but uf2 concat would be used two combine a RP2350 UF2 and a RP2040 UF2 into a single larger UF2 that could then be written to either board? (i.e. each block in the input UF2s might be targetting the same flash address)

Yes, that is generally correct:

  • uf2 combine is to combine UF2s into a single larger UF2 with one family ID
  • uf2 concat would be to concatenate UF2s into a single larger UF2 with multiple family IDs (could be RP2040 + RP2350, but could also be RP2350 code + data to go into different partitions)

uf2 concat is possible already with standard tools (eg cat) so picotool support isn't really necessary, whereas uf2 combine requires reading & editing the file data (UF2 block headers, partition table parsing) so makes sense to be implemented in picotool.

@lurch
Copy link
Copy Markdown
Contributor

lurch commented May 26, 2026

Hmm, so from my limited understanding of picotool and UF2 files, would the idea then be that uf2 combine is used to combine e.g. two RP2350 UF2s into a single larger UF2 (i.e. each block from the input UF2s gets written to a different flash address), but uf2 concat would be used two combine a RP2350 UF2 and a RP2040 UF2 into a single larger UF2 that could then be written to either board? (i.e. each block in the input UF2s might be targetting the same flash address)

Yes, that is generally correct:

  • uf2 combine is to combine UF2s into a single larger UF2 with one family ID

  • uf2 concat would be to concatenate UF2s into a single larger UF2 with multiple family IDs (could be RP2040 + RP2350, but could also be RP2350 code + data to go into different partitions)

uf2 concat is possible already with standard tools (eg cat) so picotool support isn't really necessary, whereas uf2 combine requires reading & editing the file data (UF2 block headers, partition table parsing) so makes sense to be implemented in picotool.

Now I'm slightly confused again - in the previous comment you said uf2 concat "could also be RP2350 code + data to go into different partitions", but in the opening comment for this PR (which adds uf2 combine) you said "Main use case is for combining partition tables with their partitions for loading as a single UF2 file" 😕

@will-v-pi
Copy link
Copy Markdown
Contributor Author

Hmm, so from my limited understanding of picotool and UF2 files, would the idea then be that uf2 combine is used to combine e.g. two RP2350 UF2s into a single larger UF2 (i.e. each block from the input UF2s gets written to a different flash address), but uf2 concat would be used two combine a RP2350 UF2 and a RP2040 UF2 into a single larger UF2 that could then be written to either board? (i.e. each block in the input UF2s might be targetting the same flash address)

Yes, that is generally correct:

  • uf2 combine is to combine UF2s into a single larger UF2 with one family ID
  • uf2 concat would be to concatenate UF2s into a single larger UF2 with multiple family IDs (could be RP2040 + RP2350, but could also be RP2350 code + data to go into different partitions)

uf2 concat is possible already with standard tools (eg cat) so picotool support isn't really necessary, whereas uf2 combine requires reading & editing the file data (UF2 block headers, partition table parsing) so makes sense to be implemented in picotool.

Now I'm slightly confused again - in the previous comment you said uf2 concat "could also be RP2350 code + data to go into different partitions", but in the opening comment for this PR (which adds uf2 combine) you said "Main use case is for combining partition tables with their partitions for loading as a single UF2 file" 😕

They're both true - you can use:

  1. uf2 combine to combine the partition table and the stuff in partitions into a single UF2 file with a single absolute family ID, which you can just load onto the device in one go
  2. uf2 concat (literally just cat in this case, as you don't need the block-moving-hackery) to concatenate the UF2 files for the partitions into a single UF2 file with multiple family IDs, and provided you have setup the partition table correctly and it is already loaded onto the device, they will be loaded into their respective partitions in the order they appear in the file

1 is for writing everything, as it writes to absolute addresses, ignoring the partitions already on the device

2 is for updates, as it uses the bootrom to place the UF2s into the correct partitions as per their family IDs

Currently, you have to do 2, which involves loading the partition table onto the device, rebooting, then loading the concatenated UF2 onto the device.

This PR allows you to do 1, which loads the partition table and partition data with a single picotool load/drag & drop, ignoring what is already on the device

@lurch
Copy link
Copy Markdown
Contributor

lurch commented May 26, 2026

Thanks William, I wasn't very familiar with how partitions / partition tables work on RP2350. But what you've written makes sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants