Effectively you have three, very important, programs...
Startup clears the ram, initialises variables and memory. It is very light and fast. It calls the first application entry point.
Your bootloader. Runs first and presumably checks for some trigger to hold execution and load firmware. If the trigger does not exist, it jumps to the place in memory where your app is.
Your App. Does that voodoo it does so well - and never returns.
So unless your boot-loader does the necessary initialisation work then you still need to startup code. And why would you bother since the startup files are already there and it is very light.
Normally the vector addresses (needed to run ISRs, Reset, etc) is at 0x00000000. The startup code will be close to this, then your bootloader and app and any ISRs you have written. Your program doesn't get written to RAM to run (unless you tell it to). When the bootloader calls your application it just jumps to the address in flash where your program is located.
Think of it as just another function call. Your program could implement a bootloader as simply as...
void main()
{
//
//Do Bootloader Stuff
//No trigger? Well then jump to App
//
App(); //This never returns
}
That wouldn't be a very good bootloader but you get the idea.