1

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?

sergs
  • 123
  • 1
  • 12
  • 2
    *"I have a MIPS based board (MediaTek mt7620) with a proprietary and closed bootloader (u-boot)..."* -- If that is anything like a MStar 7816 (MIPS, Linux-capable or standalone), which MediaTek acquired, then that U-Boot violates the GPL. MStar has a customized version of U-Boot, but does not make that source code available to product owners, which violates the GPL. – sawdust May 30 '19 at 19:13

1 Answers1

1

The Linux kernel is designed to run on thousands of different systems ranging from small embedded devices to large servers. It would not be practical to include the code for each possible architecture, board, or configuration in the kernel, so instead the kernel defines a set of boot requirements that must be met before it can run. It is normally the task of the boot loader to setup a proper environment and fulfil these requirements.

A "standalone application" in contrast is normally written for a specific target system (architecture, board, configuration) and takes care of setting up mostly everything by itself.

That's why u-boot handles both cases differently. If you are booting a Linux kernel, then u-boot sets everything up the way the kernel expects. If you are booting a standalone application, then it is assumed that the application will do whatever is needed.

Grodriguez
  • 21,501
  • 10
  • 63
  • 107