Best way to allocate boot loader memory space in the micro controller
I have always put my PIC 18 bootloaders at the end of program memory.  The reason you can't put them at the beginning is that this is where the interrupt vectors also are.  Assuming your app uses interrupts, since most do, you don't want the bootloader owning that section of memory.

Build the bootloader as a separate project that has a known fixed starting address near the end of memory.  I use a include file to define the things that both the main app and the bootloader need to agree on, like the start address of the bootloader and where the bootloader needs to jump to run the main app.  These need to be fixed addresses since different versions of the bootloader and main app need to be able to work together.

Execution does have to go to the bootloader on reset.  That means a GOTO instruction at location 0 to the bootloader's known fixed starting address.  Since location 0 is in the main app image, this is something the main app code has to provide.

With this kind of project, the main app usually contains a uploader.  During its normal operation, it communicates with whatever can provide a new app image.  This new app image is stored to a external EEPROM or roughly the second half of program memory.  All the complicated code for doing the communication with the host and getting the new app image is contained in the main app.

The bootloader is then a small piece of code at the end of memory that runs from reset.  It compares the main app and uploaded image versions and runs checksums on them.  Under the right conditions it copies the new app image into the main app area and then runs it.  Of course it never runs a main app that has a bad checksum.

There is one small vulnerability with this.  To update the main app image, the bootloader has to erase and then overwrite the first erase block of program memory.  Unfortunately, that is where the reset vector is.  If a power failure or glitch occurs in the few milliseconds when the GOTO at the reset vector isn't there, then the PIC is toast and can only be recovered with a external programmer.  Fortunately, that is a very small window of vulnerability, with the odds of it actually happening very very small.  Note that a glitch during erasing/writing any of the other erase pages is recoverable.  As long as the GOTO at the reset vector is there, the bootloader will be re-run, the main app checksum will fail, and it will attempt to re-write the main app from the stored app image.