Skip to main content
Visitor II
September 4, 2019
Question

Is the ROM bootloader source available somewhere?

  • September 4, 2019
  • 8 replies
  • 3920 views

I'm planning to use the built-in ROM bootloader in an STM32F4 chip for DFU uploads and having a hard time figuring out how it works exactly (in particular what pins it initializes at what moment in the boot process, and what I need to do externally to prevent it from going into e.g. SPI or UART mode). The documentation is missing some details (and experiments also give me puzzling results), so I'm looking for some more specific insight in the workings of this bootloader, which would be perfectly solved by looking at the source code.

I've read some earlier related posts, and I suspect that the sources are not currently available, but maybe someone at ST will see this as a request to change that? I would think there will not be any secrets in their bootloader sources, but it would make the bootloaders (and thus their hardware platform) a lot more usable.

Note that I realize that the ROM bootloader is not perfect and might not be a good basis for a custom bootloader, but that is not my goal (my goal is to understand and use the ROM bootloader). I also realize that the bootloader is in ROM and cannot be modified.

I also realize that using a custom bootloader in flash is also a commonly used option, but I'd prefer to use the builtin one (since that can certainly not be erased, and simplifies production).

I noticed @Community member​ mentioning in this topic that you can read back the compiled bootloader from ROM and disassemble that, which would also be helpful (but a lot harder to read, of course). He mentions his "own annotated listings", but without a link it seems. I wonder if there is any repository of such listings or dumps? If not, anyone aware of some tutorial on how to generate them? Though I guess it's a matter of dumping memory through SWD and then disassembling with something like `objdump`?

    This topic has been closed for replies.

    8 replies

    Visitor II
    September 4, 2019

    > Though I guess it's a matter of dumping memory through SWD and then disassembling with something like `objdump`?

    Instead of objdump it's better to use a proper reversing tool like Radare2 (with Cutter GUI if you would like), or Ghidra. They can even help to get a decompiled C code (not the original, of course). Try to get help in reverse engineering communities.

    IANAL, but before actually using the disassembled/decompiled code of ST's proprietary binaries I advise you to explore the legality of doing that.

    Graduate II
    September 4, 2019

    You present no good reason to decompile. System bootloader is described in AN2606 and there are a lot of programs that use DFU successful with STM32, to name dfu-utils. You put some test for some magic in some RAM that is not yet erased and if you see that magic, erase the magic and jump to the bootloader. In your user program, have some command to set that magic and to a warm reset. That is all.

    Graduate II
    September 4, 2019

    I don't know, the documentation from ST is seriously deficient and not up to date. There's almost always a good reason to understand what the micro-controller is doing in any given circumstances.

    The OP already indicated that it is the undocumented and nuanced behaviour that is problematic. Things like post-reset pin sensitivity and control flow, which can render a design difficult to program.

    Visitor II
    September 4, 2019

    > Instead of objdump it's better to use a proper reversing tool like Radare2 (with Cutter GUI if you would like), or Ghidra.

    Thanks, I'll have a look at those.

    > You present no good reason to decompile. System bootloader is described in AN2606 and there are a lot of programs that use DFU successful with STM32, to name dfu-utils.

    Ok, let me make some of the questions I have (and which I cannot find answered in AN2606) explicit. I'm looking at the STM32F401xE

    • What are the exact pin modes used by the bootloader? Table 46 in AN2606 lists them, but e.g. for SPI it says "push-pull pull-down mode". What does that mean? "push-pull" means "output" to me (so drive low or drive high), so what good would a pull-down do? And the same mode is listed for all SPI pins, while some of them would need to be input and some output?
    • When are pins initialized exactly? e.g. to detect a sync byte on the UART, the bootloader only needs to enable its RX pin, but maybe it also enables it TX pin (i.e. set to output) right away? Or maybe only after receiving the sync byte on RX? There is a note in the changelog for the STM32F105xx/107xx (section 14.3.4) that suggests that for that chip, the TX pin was originally initialized right away, but this was later changed to initializing it later to prevent sinking high currents when the TX pin is also used for USB. But other than that note, the pin list for those chips have no indication of this, and the documentation for my STM32F401xE has no mention either, but does have the same pin shared between TX and VBUS. The bootloader version number is newer, so maybe it has the "new" behaviour?
    • Is the NSS pin used for SPI active-high or active-low? The latter is more common, but the docs say there is a pull-down (confirmed by measurements), so that would suggest that it is active-high (so the SPI slave is inactive by default and can be made active by driving NSS high). However, figure 4 on page 32 shows the SPI hardware connection and shows tying NSS to GND to make/keep the SPI slave active, so that suggests active-low. But then how to keep the slave *inactive*? Tie the pin high? But I also want to use the pin for GPIO when the bootloader is not active, so then I'd rather use a pullup resistor (but it would need to be small enough to compete with the builtin pulldown...).
    • How does the bootloader decide what protocol to use exactly (e.g. when does it *stop* trying different protocols and will it select one)? The flowchart in figure 31 says vague things like "USB cable Detected" (but there is no VBUS connection, so cable insertion cannot be detected AFAICS. Maybe this means "USB reset" or "USB enumeration" instead? Or "SPIx detects Synchro mechanism", which I guess means receiving the "Syncrhonization byte" defined in AN4286, or does it happen when the NSS pin is pulled low already?

    I guess that clarifying these things in the official docs would also be great and a lot easier than having to read the source code. However, being able to read the source code would make it possible to also answer these questions (and more, these are just the things that I remembered wondering and needing recently, I can imagine that for different usecases, other details can be important).

    Does this help clarify the background of my question?

    > and there are a lot of programs that use DFU successful with STM32, to name dfu-utils. You put some test for some magic in some RAM that is not yet erased and if you see that magic, erase the magic and jump to the bootloader. In your user program, have some command to set that magic and to a warm reset. That is all.

    That part is actually already clear, I've made the "warm reset" part and dfu-utils upload work. However, I need to make this reliable and ensure the bootloader 1) does not jump into e.g. SPI mode accidentally, breaking USB uploads and 2) does not put some pins in output mode that would cause a short-circuit or overcurrent condition. Both of these I can fix by careful pin selection and PCB design, but then I do need to know what the constraints are exactly.

    Graduate II
    September 4, 2019

    To more completely quote myself, I said "Created my own annotated listings here", which basically means I did it myself, it took effort and it is work product. Publishing other people's work tends to get into a more complex area, whereas interfacing, vulnerability testing, and due-diligence tend to be broadly acceptable use cases.

    One could perhaps use objdump or fromelf, but these are a bit like Butter Knives, I use instruments which are a lot sharper, which I fashioned myself. The use of simpler/prolific tools tends to be improved significantly with post-processing to reformat to a preferred style with flow and interaction paths identified.

    I can also sight-read code, so it doesn't matter much if it is C, Assembler or whatever.

    Visitor II
    September 4, 2019

    > To more completely quote myself, I said "Created my own annotated listings here", which basically means I did it myself, it took effort and it is work product.

    That makes sense. I think I was hoping that "here" in your sentence was supposed to be a link, but reading it as "here in-house" also makes sense. I understand that publishing that might not be trivial. Thanks for you addition, though :)

    Graduate II
    September 4, 2019

    Did you have a look at the Bootloader selection flows presented in AN2606. It also clearly tells what facilities are involved. But if you want full controll over the bootloader, write your own or look on the web for existing ones.

    Visitor II
    September 4, 2019

    Yeah, I have looked at the selection flow, but it is lacking in detail (as indicated in my reply above), and also does not paint the whole picture (it does not detail when pins are initialized, for example). Also, I am not looking for full control over the bootloader, I'm looking the understand the builtin one so I can use it without problems later on.

    Super User
    September 4, 2019

    At the end of the day, the bootloader sits in transistors we are paying for, so it would be nice to have a more thorough description of the details. Even if AN2606 is the best written and best maintained of all STM32 appnotes (which is kind of sad).

    Although, the same applies to many other transistors on that chip...

    JW

    Super User
    September 4, 2019

    After doing few projects with several STM32s I hardly used the "system memory" bootloader at all.

    For initial programming I always use the debug interface, then my own bootloaders.

    Of course I am not an expert by any means but I'd rather prefer that ST leaves the "system memory"

    one-time-programmable by end user.

    So that we could make custom bootloaders perfectly tailored - and have the source too.

    -- pa

    Graduate II
    September 4, 2019

    Production programming via serial interfaces can be scaled very cheaply, especially in products that already expose the interfaces.

    The transistor for the array are limited, the code however does not use the optimizer. Functionality if broken down cleanly and exported in unused vectors, could provide significantly more flexibility and consistency.​

    Graduate II
    September 14, 2019

    > the code however does not use the optimizer

    That could be indication that the code is of bad quality and has stability problems. Just like HAL, CubeMX, examples and... all code from ST!? I'm wondering - is the system memory bootloader built no HAL? It would make sense, unfortunately... Maybe someone has figured it out?

    Graduate II
    September 14, 2019

    They don't trust the Keil compiler/tool chain.

    The firmwares do not look to use HAL constructs​.

    Visitor II
    December 14, 2020

    I submitted an "Idea" to ST, asking them to publish bootloader source code. Let's see if they reply?

    If you're also interested in the bootloader sources, be sure to vote on the idea: https://community.st.com/s/ideazone#0873W000000PAwtQAG