I have a MIPS based board (MediaTek mt7620) with a proprietary and closed bootloader (u-boot) with cut off a lot of functionality, like booting a standalone application
. (I'm not allowed to change/reflash this bootloader, 'cause a lot of customers use this board and if we were updating the bootloader and it failed we would faced with a lot of bricks :) (bootloader supports a boot over tftp
protocol) )
I'm trying to change a boot sequence provided by a board manufacturer: ROM bootloader --> flash bootloader (u-boot) --> linux kernel to a: ROM bootloader --> flash bootloader (u-boot) --> boot trap --> linux kernel. For another board (mt7621) with a u-boot which supports a booting a standalone application
I was able to create some boot trap
u-boot image (standalone app) and put it into the flash instead of a linux kernel (I moved linux kernel down). (this boot trap
makes some work, loads and boots the linux kernel by using a ranand_read/do_bootm
functions provided by the u-boot via a jump table.
As I mentioned, a u-boot for an mt7620-based board doesn't support booting a standalone application
, so I decided to create a boot trap
as a u-boot linux image (not as a u-boot standalone app image) keeping code of boot trap
almost the same (I changed only function signature: for a standalone app u-boot image 2 args get passed, for a linux u-boot image - 4; and load/entry addresses).
This is a log from a serial port, for an mt7621-based board:
## Booting image at bc140000 ...
Image Name: Boot trap
Image Type: MIPS U-Boot Standalone Program (uncompressed)
Data Size: 524 Bytes = 0.5 kB
Load Address: a0600000
Entry Point: a0600000
Verifying Checksum ... OK
OK
boot trap: got a control
boot trap: load a real kernel...
.......................
boot trap: boot a real kernel...
## Booting image at 88000000 ...
Image Name: OpenWrt Linux-3.10.14
Image Type: MIPS Linux Kernel Image (lzma compressed)
Data Size: 1494179 Bytes = 1.4 MB
Load Address: 80001000
Entry Point: 80001000
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 80001000) ...
## Giving linux memsize in MB, 256
Starting kernel ...
LINUX started...
and for an mt7620-based board:
## Booting image at bc140000 ...
Image Name: Boot trap
Image Type: MIPS Linux Kernel Image (lzma compressed)
Data Size: 345 Bytes = 0.3 kB
Load Address: 80001000
Entry Point: 80001000
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 80001000) ...
## Giving linux memsize in MB, 256
Starting kernel ...
As you can see, code in the 'boot trap' (as a linux u-boot image) got stuck, I have no JTAG
debugger, so I can only guess that some exception happend and board stuck in an infinity loop inside that exception handler.
I see in u-boot sources for an mt7621-based board (I have them :)) such lines of code:
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
...
switch (hdr->ih_type) {
case IH_TYPE_STANDALONE:
appl = (int (*)(int, char *[]))ntohl(hdr->ih_ep);
(*appl)(argc-1, &argv[1]); // <--- pass a control to a standalone app
return 0;
...
switch (hdr->ih_os) {
default:
case IH_OS_LINUX:
do_bootm_linux (cmdtp, flag, argc, argv,
addr, len_ptr, verify);
break;
...
and next lines:
void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[],
ulong addr, ulong * len_ptr, int verify)
{
...
void (*theKernel) (int, char **, char **, int *);
theKernel = (void (*)(int, char **, char **, int *)) ntohl (hdr->ih_ep);
...
theKernel (linux_argc, linux_argv, linux_env, 0); // <--- pass a control to a linux kernel
}
So the question is what's a difference between booting a linux kernel and a standalone app? Why linux has to setup a stack pointer after it gets a control (linux/arch/mips/kernel/head.S) if we have a valid C environment already? Why linux has to do so much work before it passes a control to itself first C function (in a standalone app we're able to place a C function code directly into an addres, u-boot passes control to)?
Why it's impossible to place a code in an address a u-boot passes a control to and just let it run as I made for standalone app?