UF2 Loader release

The SDBoot/multi_booter bootloader that @adwuard and @guu amongst others have done a bunch of work on is fantastic but it has a couple of glaring limitations that I couldn’t tolerate:

  1. It requires recompiling every application with a custom linker script
  2. It only reads .bin files instead of the usual .uf2 format, so various platform safety features are lost

I’ve just released a reworked version of the bootloader that fixes these two issues. Just stick (almost) any uf2 file you like into the /firmware directory on the SD card, and this loader can use it directly.

I’ve also pulled across most of the UI updates that are present in the multi-booter version. If an application is loaded, it will automatically boot unless UP is held during power on. The first entry in the file list (shown in square brackets) will show the filename of the loaded application if one is present, and will boot to it directly without reflashing if selected.

Holding DOWN during power-on instead will put the Pico into BOOTSEL mode if you need it.

For now, only the Pico 1 is supported, as Pico 2 requires a very different implementation which I’m currently working on adding.

8 Likes

a couple of quick questions:

  1. “top of flash” means highest address, correct? So our boot stage2 directly goes to “high mem” and only drops back to prog_info->addr if booting in normal mode?
    • apps like picomite writes to flash and not aware of the loader, potential overwrite?
  2. for pico2, I skimmed through the datasheet (thanks for the link) section 5 – what’s the plan? re-compile everything to target a higher address and then translate? why can’t we just use the default, 2040-like behavior?
  3. any change that we support data restore? (dump/restore all flash minus the range specified in the uf2)

Fantacy !
Will it be better to make the boot menu show every time bootup but auto-select the last firmware after a short timeout like GRUB or Windows Bootloader do on a PC? PicoCalc boot very fast,1~2 second time out wouldn’t make a different but will make the select operate more easy (clicking one button is easyer than hold down 2 buttons every time when boot up)

If the program tries to overwrite the bootloader it will succeed, yes. So don’t do that. Unfortunately the RP2040 doesn’t have a means of write protecting sections of flash.

As far as PicoMite goes, just stay in the first flash slot, at least for now. But really you should use the SD card for storage.

The RP2350 has a completely redesigned boot system, it doesn’t execute boot2 in the way that the RP2040 does. So it can’t work. But the added capabilities it has means there is a much nicer way to do the same thing, with the application living in its own partitioned space.

Autobooting into the application wasn’t my original choice, it’s what multibooter does. But I’m increasingly coming around to it. Most of the time you won’t be changing application every time you turn on the unit. And holding down a key when you want to do so is pretty straightforward. If it’s really bothersome, it’s trivial to compile a custom version.

For devs who want to know how big the bootloader is so they don’t overwrite it, a pointer to the start of the bootloader area is stored in the 4 bytes at the very end of flash (i.e. XIP_BASE+0x1FFFFC). It’s not there yet (it’s in v1.1) but I’ll add a magic value 0xe98cc638 at (XIP_BASE+0x1FFFF8) shortly so it’s clear when the value is valid.

I do that because boot2 can’t be automatically built with the bootloader entry point (it’s built and linked separately) and this way it can be hardcoded with a known address.

3 Likes

Even if the user doesn’t decide to use any of the flash slots in PicoMite, it will save a certain amount of data to flash. That’s how it stores the OPTION values, but it also stores whatever MMBasic file you last loaded in the editor to flash, and possibly some other things. The 3 flash slots also seem to be regularly used by people. At the very least, one of them is useful to use AUTORUN to run some code at power on. But some people use them to store libraries and such.

So if there’s no provision for preventing PicoMite from overwriting the bootloader, then it’s probably wise to just suggest no one uses it with PicoMite. The existing multibootloader patched PicoMite to shift where the flash data was stored. So that might work here too.

It would be nice if PicoMite’s flash area could be saved and loaded to SD as needed between boots (and ideally any firmware’s custom flash area if it has one), but if that’s not possible, it’s probably dangerous to just let PicoMite write into sensitive areas of flash and clobber the bootloader. (And I’m pretty sure it will!) Hopefully that wouldn’t brick the pico and the “nuke” firmware could be used to wipe it so it could be used again.

There’s actually no risk of PicoMite overwriting anything, as it doesn’t come close to using all of the available flash. Options are saved in a 20k block at 832k offset, immediately followed by the three flash slots of 128k each, and then the optional module buffer which is at most 512k. That leaves a guard region of 164k before getting to the bootloader.

Saying “nobody should use this with PicoMite” seems a tad extreme.

Also, the job of saving/restoring those flash slots to SD falls entirely on PicoMite itself.

1 Like

Sounds good. I didn’t realize there was enough space already for it all.

This made it sound like PicoMite could easily overwrite the bootloader. Hence my post.

It’s fine, it forced me to actually figure out the full details instead of just handwaving it. :smiley:

1 Like

I’ve made a v1.1 release with the magic number for bootloader detection added. If XIP_BASE+0x1ffff8 is 0xe98cc638 then XIP_BASE+0x1ffffc can be trusted to be the bootloader start address, and all addresses below that are safe for an application to write to.

1 Like

I could be missing something. That is 2MB in, what happens on the Pico 2 with 4MB of flash, or other boards with more? How large is the boot loader, is it just a single 4k flash sector that needs to be respected?

The bit you’re missing is that the Pico 2 isn’t currently supported. However when it is, it won’t need this scheme since the application will be properly partitioned away from the bootloader.

For RP2040 boards with different amounts of flash, both the bootloader and the applications would need to be recompiled anyway. This is another reason why I specifically say Pico 1 instead of RP2040.

And I wish the bootloader was 4k! It’s a full GUI application with filesystem support, it’s actually about 140k right now, and that’s using MinSizeRel and nanolib.

2 Likes

Ok, got it! It sound like the Pico 2 will be much cleaner.

Remember for the PicoMite/WebMite the firmware uses all flash above the flash slots/modbuffer as the A: drive using LittleFS. It automatically sizes the A: drive to the size of the actual flash chip.
In addition new releases that have any significant changes typically re-write all flash.

1 Like

It’s done a poor job of wiping the bootloader on my unit so far… :smiley:

I don’t think LittleFS actively wipes flash unless it needs the space (and I’d be extremely suspicious of it’s implementation if it did.) All it needs to do is clear it’s directory metadata.

But point taken. It’s a good opportunity to write a standard implementation of my flash size check.

To clear it up: with pico2+partition+address translation, there’s no risk of overwriting, right?
Writing outside the partition should cause a bus fault.

Another question: could we initialize SPI and load sdboot from sdcard instead (no filesystem, just follow some convention and read a consecutive block at an offset)?

What’s the size limit of stage2?

Boot stage 2 has to be exactly 256 bytes, and it’s packed to the gills already. I don’t see anything else fitting in there!

…would have been a neat trick, though.

Edit: it just occurred to me that an alternative would be to turn the bootloader into a minimal stage3 that can either launch the application or load one into RAM from the SD card. Since there’s no real need for the UI unless the SD card is present. The UI would just be a PICO_NO_FLASH application. Hmmm.