To expand on the accepted answer…
When an x86 PC starts, its CPU is executing in 16-bit real-mode and it runs the code stored in BIOS. After BIOS performs POST and initial configuration it reads the first 512 bytes from the beginning of the boot disk and transfers the execution there — it's the initial code of a boot loader which is supposed to do the rest.
Now consider what's rest. In the simplest case the boot loader should be able to locate and load the kernel's image and transfer the execution there. Older de-facto standard Linux loader, lilo
, kept a contiguous map of all the sectors on which the kernel were stored. But the picture changed quite a bit since then: more filesystems came into use, it became customary to keep the kernel on a RAID device or on an LVM logical disk or on a stack of these all. Computers started to feature more pluggable disks which means arbitrary ordering of their initialization and hence problems with naming. Now consider that these days bringing up a generic system based on Linux requires some early-available user-space tools which are kept on the so-called "initrd" (initial RAM disk) or "initramfs" (initial RAM filesystem), so actually the boot loader loads not only the Linux kernel but also a matching initramfs for it.
So, the boot loader's task is:
- Bootstrap itself — those 512 bytes can sensibly only find and load something more complicated.
- Discover and initialize all the layers needed to access the boot filesystem (the filesystem containing the kernel and its initramfs).
- Load it all and then transfer the control to the kernel.
Now consider that most people find it useful to be able to somehow visualize and control this process, so there's a requirement for the boot loader to be able to present a menu of a sort and an ability to tweak what will be loaded, and how. An ability to load an alternative kernel might also be a bonus (for instance, a new kernel installed from the repository of Debian security updates never removes the existing kernel — rather, that one is kept aside and is available for booting if a regression is found in a new one).
So, as can be seen, unless we deal with some kind of embedded system with very tight memory/storage space requirements, and in which no one controls how the kernel is loaded, it's unreasonable to put this functionality right into the kernel, more so, since the boot loader is an inherently highly hardware platform-dependent piece of software. That's why boot loader exists and why on a generic system the need to use one is mainly inescapable.