Wednesday, August 12, 2015

Kernel Entry from u-boot (MIPS)



Lets explore how u-boot to kernel transition happening from MIPS architecture point of view. Before understanding the flow, we should be aware of the following basic questions.

1. What is uImage ?? 

          An image file that has a U-Boot wrapper (installed by the mkimage utility) that includes the OS type and loader information.
2. How to convert Linux kernel to uImage ??
           As part of kernel compilation process, uImage should be specified explicitly for creating uImage.
For example,

make ARCH=mips CROSS_COMPILE=some-mips-toolchain-gcc uImage -j24
                                                     ^^^^^^  
3. What is the role of mkimage here ??

            mkimage is a tool which is used for generating the uImage. This script  http://lxr.free-electrons.com/source/scripts/mkuboot.sh in linux kernel tree calls the mkimage.
While creating uImage, the entry point address of the Linux kernel(kernel_entry) is specified. Refer http://lxr.free-electrons.com/source/scripts/Makefile.lib
VMLINUX_ENTRY_ADDRESS is the starting address of Linux kernel.
236 ifdef CONFIG_PHYSICAL_START
237 load-y                                  = $(CONFIG_PHYSICAL_START)
238 endif
239 entry-y                         = 0x$(shell $(NM) vmlinux 2>/dev/null \
240                                         | grep "\bkernel_entry\b" | cut -f1 -d \ )
... 
271 
272 bootvars-y      = VMLINUX_LOAD_ADDRESS=$(load-y) \
273                   VMLINUX_ENTRY_ADDRESS=$(entry-y)
274 

Lets come to our actual discussion. I hope the reader have basic idea of how to use u-boot prompt for loading Linux kernel.
the bootm command is called after all preliminary commands like loading kernel to memory through tftp or some other medium.
bootm command reads the entry point address mentioned during the creation of uImage.
 300 static void boot_jump_linux(bootm_headers_t *images)
 301 {
 302         typedef void __noreturn (*kernel_entry_t)(int, ulong, ulong, ulong);
 303         kernel_entry_t kernel = (kernel_entry_t) images->ep; <----- HERE
 304         ulong linux_extra = 0;
 305 
 306         debug("## Transferring control to Linux (at address %p) ...\n", kernel);
 307 
 308         bootstage_mark(BOOTSTAGE_ID_RUN_OS);
 309 
 310         if (mips_boot_malta)
 311                 linux_extra = gd->ram_size;
 312 
 313 #ifdef CONFIG_BOOTSTAGE_FDT
 314         bootstage_fdt_add_report();
 315 #endif
 316 #ifdef CONFIG_BOOTSTAGE_REPORT
 317         bootstage_report();
 318 #endif
 319 
 320         if (images->ft_len)
 321                 kernel(-2, (ulong)images->ft_addr, 0, 0);
 322         else
 323                 kernel(linux_argc, (ulong)linux_argv, (ulong)linux_env,
 324                         linux_extra);
 325 }
Refer u-boot code where the call to Linux kernel occurs.
In MIPS, the kernel_entry function in arch/mips/kernel/head.S will be called. Now we are officially in kernel code.
All hardware related initialization are done then start_kernel is called.

No comments:

Post a Comment