Wednesday 4 July 2012

Bootloader and U-Boot

Bootloader:

Assuming you want to have a bootloader that can boot-up linux kernel.
A very basic bootloader would do a simple memory read/write test, initialise Uart, copy the kernel image from flash to ram, then perform a jump to the kernel starting address.

To expand the basic bootloader, we can add:
- wait for a few seconds for user interruption when booting
- add a loop to accept and process user input
- configure more on-board hardware resources, such as Ethernet controller, Sata controller, Usb controller

ROM Bootloader:

Certain micro-controller contains ROM Bootloader (RBL), which resides in the ROM of the micro-controller. The RBL supports booting from various memory devices (master mode), or from external master (slave mode). When using external master, the PC is used as the UART boot master via UART boot mode. The RBL supports limited number of NAND devices.

Upon reset or power-up, the micro-controller begins executing code from its RBL. The RBL read BOOTCFG register to determine the boot mode. 

Normally, a secondary boot loader, known as User Boot Loader (UBL) would be loaded by RBL. UBL could be used to initialise the memory controller, setting system clock, and download a tertiary bootloader, such as U-Boot.

In NAND boot mode, the RBL requires UBL to exist in the NAND memory, to load the tertiary boot loader from NAND to RAM. In NOR boot mode, the UBL is not required. The RBL locates the UBL image, via magic number in the UBL header. Then RBL copy UBL image to IRAM, then begin executing it.

The UBL will locate the tertiary bootloader image, load it from NAND to RAM, then jump to the entry point address.

U-Boot:

U-Boot is a popular open source bootloader. It has been ported to ARM, PPC, MIPS platform.


  • For PPC porting, modify files in:

cpu/mpc8xxx/
board/freescale/mpc8xxx/
lib_ppc/
include/asm-ppc

  • For ARM porting, modify files in:

cpu/arm926xxx/
board/mv88xxxxx/db88xxxxxx/
lib_arm/
include/asm-arm

important files:
common/main.c - contain main_loop() function
common/cmd_bootm.c - contain bootm command handling
post/tests.c - contain array of functions for post tests
include/configs/MPC8xxx.h - contain u-boot env settings, such as bootargs
include/configs/db88xxxxxx.h

Example: Building U-Boot:
make MPC8xxx_NAND_config    (for PPC)
make

make distclean
make db88xxxxxxxx_config  (for ARM)
make

U-Boot on ARM9 boot up sequence:

cpu/arm926xxx/start.S

  • reset
  • early DRAM init
  • relocate u-Boot to DRAM
  • stack_setup
  • clear_bss
  • call start_armboot


lib_arm/board.c

  • start_armboot()
  • (*init_fnc_ptr)() - looping thru init_sequence[] array
    • cpu_init
    • board_init
    • interrupt_init
    • serial_init
    • console_init_f
    • display_banner
    • dram_init
  • nand_init()
  • devices_init()
  • console_init_r()  - set stdin, stdout, stderr
  • for (;;) main_loop() - parsing user input

DRAM Initialisation:

Set Icache
Twsi Init
Dram Interface Detect
Read from On-board DRAM or DIMMS
Dram Interface Config
Get total size

DRAM Serial Presence Detect (SPD) in U-Boot:

For DRAM on DIMMS, we can read its EEPROM to extract the SPD data
1) Setup the twsi slave address, type, offset
2) Read data from the twsi
3) calculate checksum, compare checksum
4) analyze the SPD data, such as DIMM type, row and col addr, number of banks, data width, cycle time, refresh interval, burst length, CAS latency, DIMM bank density, memory size

Add new commmand:

common/cmd_xxx.c
include/commands.h
   #define U_BOOT_CMD

use U_BOOT_CMD macro to fill in cmd_tbl_t structure

U-Boot boot settings:

For example, a board with 64MB RAM, and booting from network, using ramdisk.

bootargs=root=/dev/ram0 rw initrd=0xc2000000,16M console=ttyS2,115200n8
ramboot=tftp 0xc2000000 rootfs.ext2.gz;tftp 0xc0700000 uImage;bootm 0xc0700000
bootcmd=tftp 0xc2000000 rootfs.ext2.gz;tftp 0xc0700000 uImage;bootm 0xc0700000




No comments:

Post a Comment