The ST's internal bootloader is only good for factory programming. Applications are so different and it would not make sense to have one generic updater for them all. Depending on the user interfaces and types of device, you shall implement the updater yourself. The best fit is different for every project. As this is needed for every project, you'll start to re-use the code from previous projects and so it will become much easier for every other project.
Different approaches for different projects:
* Application/bootloader split. Either the application uses some of its communication interfaces to receive an update and store it to another flash region, then bootloader copies it to real location or the bootloader has communication interface too. Sometimes, you can even run from RAM and do in-place update inside the application itself without bootloader at all (with possibility to brick the board).
* Communication interface. USB device port (usb DFU, usb-serial etc)? USB host port (update via usb memory stick)? Ethernet (TFTP? Upload update file via web interface? Download from central server?) Can-bus? Native serial port?
* Storage. Where to store the update package if it needs to be stored. If the board has external flash, it would be cheaper to have it there instead of doubling the uc internal flash size.
* Composition of update package. Sometimes, there has to be additional data besides the uC fw. For example, FPGA bitstream. Graphics/fonts/data stored to external flash. You'll need to handle those as well to have one single update image.
* Actions needed on update. Sometimes, configuration data has to be migrated. Sometimes, something else on board needs to be re-programmed, too...
* Security. Encryption algorithm. Keys. Checksumming.
Different vendors have application notes about bootloader design. Most of that can be easily used on whatever platform, you'll need to implement the flash access of your target system and the communication interface. If your application already has a communication interface, just add the update package upload functionality there. Then you need to implement the bootloader->application launch function and thats it. Change your application linker script to locate it at higher address above bootloader. For Cortex-M0 parts (without VTOR), you'll need to investigate vendor-specific interrupt table relocation possibilities, otherwise redirect VTOR and start the application.