心语.菲 / openWRT / 【U-Boot 启动过程及简单代码分析

分享

   

【U-Boot 启动过程及简单代码分析

2016-02-17  心语.菲
http://www.right.com.cn/forum/thread-141333-1-1.html 

本帖最后由 hackpascal 于 2014-10-28 22:10 编辑 

【U-Boot 启动过程及简单代码分析

这里以 AR7241 的 U-Boot 为例

MIPS 架构简介
MIPS 地址空间:
这里说的是地址空间,不是内存空间。内存只是映射在一部分地址空间上而已。
内存分为4段 (Kuseg、Kseg0、Kseg1、Kseg2),其中 Kseg0 (0x80000000 ~ 0x9fffffff) 为缓存段,直接映射在物理地址段上。
Kseg1 (0xa0000000 ~ 0xbfffffff) 为非缓存段,直接映射在物理地址段上。
Kuseg 和 Kseg2 需要经过地址转换才能访问。
在 CPU 复位时,缓存未被初始化,只有 Kseg1 能够被直接访问。

AR71XX 物理段:
内存、Flash、IO寄存器等都被映射在物理段上
范围为 0~0x1fffffff,访问时需要通过宏 KSEG0ADDR(_addr) 来通过 Kseg0 访问或 KSEG1ADDR(_addr) 来通过 Kseg1 访问。
物理地址一般不能直接访问,都需要通过 Kseg0 或 Kseg1 来访问。

主要的映射范围:
DDR:0~0x0fffffff (这一段直接映射物理内存,一般通过带缓存的 Kseg0 来访问,以便加快速度)
I/O空间:0x10000000 ~ 0x1dffffff (这一段直接控制硬件,必须通过 Kseg1 来访问)
SPI Flash 空间:0x1f000000 ~ 0x1fffffff (这一段映射闪存的前 16MB 数据)

AR71XX 启动过程

CPU 上电时,物理段中,SPI Flash 的前4MB 被循环映射在 0x1f000000 上,因此会被重复 4 次。
执行地址为 KSEG1ADDR(0x1fc00000),即 0xbfc00000。

*注意:U-Boot 在编译时,实际设置的基址,即启动地址为 KSEG0ADDR(0x1f000000),即 0x9f000000。下面会讲到为什么要这么设置。

U-Boot 中的起始代码在 cpu/mips/start.S 中:

  1. _start:
  2. #ifndef COMPRESSED_UBOOT
  3.         RVECENT(reset,0)        /* U-boot entry point */
  4.         RVECENT(reset,1)        /* software reboot */
  5.         RVECENT(romReserved,2)
  6. ----------------------------------------------------省略----------------------------------------------------
  7.         RVECENT(romReserved,125)
  8.         RVECENT(romReserved,126)
  9.         RVECENT(romReserved,127)

  10.         /* We hope there are no more reserved vectors!
  11.          * 128 * 8 == 1024 == 0x400
  12.          * so this is address R_VEC+0x400 == 0xbfc00400
  13.          */
复制代码

以上代码设置异常向量,不需要理解
第一句 RVECENT(reset,0) 为一个跳转,直接转到下面的代码进行运行

  1.         .align 4
  2. reset:
  3.         /* set GPIO_OE  -- added by lsz to fix the LED issue 09.03.25 */
  4.         li                a1, AR7100_GPIO_OE
  5.         lw                v1, 0(a1)
  6.         li                v0, 0x3fdff        
  7.         or                v1, v1, v0
  8.         sw                v1, 0(a1)
  9.         lw                v0, 0(a1)
  10.         lw                v0, 0(a1)

  11. ----------------------------------------------------省略----------------------------------------------------

  12.         /* CONFIG0 register */
  13.         li        t0, CONF_CM_UNCACHED
  14.         mtc0        t0, CP0_CONFIG
复制代码

以上代码前半部分通过设置 GPIO 来点亮路由的 LED。后半部分设置 CPU 相关参数,不需要理解
以上代码没有包含使用相对地址的指令,也就是说,无论这段代码在 CPU 地址空间的何种位置,都能够正常执行
因此虽然 CPU 的执行地址为 0xbfc00000,以上代码依然能执行

  1.     /* Initialize GOT pointer.*/
  2.         bal     1f
  3.         nop
  4.         .word   _GLOBAL_OFFSET_TABLE_
  5.         1:
  6.         move    gp, ra
  7.         lw      t1, 0(ra)
  8.         move        gp, t1
复制代码

以上代码加载了用于 U-Boot 重定位的 GOT 指针,它是 U-Boot 在内存中进行自身移动的关键

  1.         la      t9, lowlevel_init
  2.         jalr    t9
  3.         nop
复制代码

以上代码进行 CPU 频率设置,超频就是在这里实现的

  1.         la        t0, rel_start
  2.         j        t0
  3.         nop

  4. rel_start:
复制代码

以上代码很关键,它实现了 U-Boot 的执行地址的转移
假设当前 CPU 的执行地址在 0xbfc00000 + x
那么执行此段代码后,CPU 执行地址将跳转到 0x9f000000 + x 处进行执行
前面提到了 CPU 在复位时,物理段 0x1f000000 处循环映射 4 次 Flash 的前 4MB,而 U-Boot 大小只有100KB多,
因此 0x1f000000 跟 0x1fc00000 处的数据是一样的,这就实现了运行地址的转移。
至于为什么不跳转到 0xbf000000 + x 处运行,是因为 AR71XX CPU 在复位时,缓存可用,因此通过 Kseg0 段执行,可以加快速度。

  1.         /* REMAP_DISABLE */
  2.         li        a0, AR7100_SPI_CLOCK
  3.         li        t0, 0x43
  4.         sw        t0, 0(a0)
复制代码

以上代码的作用是禁用物理段 0x1f000000 的 4MB Flash 数据循环映射,以便让 0x1f000000 能够映射 16MB 的 Flash 数据


  1.         /* Initialize caches...
  2.          */
  3.         /* 初始化缓存 */
  4.         la      t9, simple_mips_cache_reset
  5.         jalr    t9
  6.         nop

  7.         /* ... and enable them.
  8.          */
  9.         /* 启用缓存 */
  10.         li        t0, CONF_CM_CACHABLE_NONCOHERENT
  11.         mtc0        t0, CP0_CONFIG

  12. ----------------------------------------------------省略----------------------------------------------------

  13. #if defined(CONFIG_AR7100) || defined(CONFIG_AR7240)
  14.     /* 将缓存锁定在 Kseg0 低端处 */
  15.     la      t9, mips_cache_lock_24k
  16.     jalr    t9   
  17.     nop
  18. #endif
  19. #endif /* #ifndef COMPRESSED_UBOOT */
  20.         /* 将栈指针指向缓存 */
  21.         li        t0, CFG_SDRAM_BASE + CFG_INIT_SP_OFFSET
  22.         la        sp, 0(t0)

  23.         /* 进入 C 环境 */
  24.         la        t9, board_init_f
  25.         j        t9
  26.         nop
复制代码

这段代码的作用是初始化缓存,并将缓存锁定在 Kseg0 上,用作临时的栈空间
此时内存并未初始化, Kseg0 对应的 0x80000000 ~ 0x8fffffff 还不能被访问,因此需要用缓存代替。
然后跳转到 board_init_f 进行执行

下面开始在 C 环境中运行
文件:lib_mips/board.c

  1. void board_init_f(ulong bootflag)
  2. {
  3.         gd_t gd_data, *id;
  4.         bd_t *bd;
  5.         init_fnc_t **init_fnc_ptr;
  6.         ulong addr, addr_sp, len = (ulong)&uboot_end - CFG_MONITOR_BASE;
  7.         ulong *s;
  8. #ifdef COMPRESSED_UBOOT
  9.         char board_string[50];
  10. #endif
  11. #ifdef CONFIG_PURPLE
  12.         void copy_code (ulong);
  13. #endif


  14.         /* Pointer is writable since we allocated a register for it.
  15.          */
  16.         gd = &gd_data;
  17.         /* compiler optimization barrier needed for GCC >= 3.4 */
  18.         __asm__ __volatile__("": : :"memory");

  19.         memset ((void *)gd, 0, sizeof (gd_t));

  20.         /* 依次运行初始化函数 */
  21.         for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
  22.                 if ((*init_fnc_ptr)() != 0) {
  23.                         hang ();
  24.                 }
  25.         }

  26. #ifdef COMPRESSED_UBOOT
  27.         checkboard(board_string);
  28.         printf("%s\n\n",board_string);
  29.         gd->ram_size = bootflag;
  30.         puts ("DRAM:  ");
  31.         print_size (gd->ram_size, "\n");
  32. #endif

  33.         /*
  34.          * Now that we have DRAM mapped and working, we can
  35.          * relocate the code and continue running from DRAM.
  36.          */
  37.         addr = CFG_SDRAM_BASE + gd->ram_size;

  38.         /* We can reserve some RAM "on top" here.
  39.          */

  40.         /* round down to next 4 kB limit.
  41.          */
  42.         addr &= ~(4096 - 1);
  43.         debug ("Top of RAM usable for U-Boot at: %08lx\n", addr);

  44. ----------------------------------------------------省略----------------------------------------------------

  45.         /*
  46.          * Save local variables to board info struct
  47.          */
  48.         /* 记录内存基址及大小、串口波特率 */
  49.         bd->bi_memstart        = CFG_SDRAM_BASE;        /* start of  DRAM memory */
  50.         bd->bi_memsize        = gd->ram_size;                /* size  of  DRAM memory in bytes */
  51.         bd->bi_baudrate        = gd->baudrate;                /* Console Baudrate */

  52.         memcpy (id, (void *)gd, sizeof (gd_t));

  53.         /* On the purple board we copy the code in a special way
  54.          * in order to solve flash problems
  55.          */
  56. #ifdef CONFIG_PURPLE
  57.         copy_code(addr);
  58. #endif

  59.         /* 执行代码转移 */
  60.         relocate_code (addr_sp, id, addr);

  61.         /* NOTREACHED - relocate_code() does not return */
  62. }
复制代码

board_init_f 的作用为进行内存、时钟、串口等设备的初始化,并为 U-Boot 的运行划分内存。

初始化函数位于 board_init_f 函数上方

  1. init_fnc_t *init_sequence[] = {
  2. #ifndef COMPRESSED_UBOOT
  3.         timer_init,    /* 初始化时钟 */
  4. #endif
  5.         env_init,                /* initialize environment */ /* 初始化环境变量 */
  6. #ifdef CONFIG_INCA_IP
  7.         incaip_set_cpuclk,        /* set cpu clock according to environment variable */
  8. #endif
  9.         init_baudrate,                /* initialze baudrate settings */
  10. #ifndef COMPRESSED_UBOOT
  11.         serial_init,                /* serial communications setup */ /* 初始化串口,这样 TTL 才有输出 */
  12. #endif
  13.         console_init_f,   /* 初始化控制台环境 */
  14.         display_banner,                /* say that we are here */ /* 显示 U-Boot 1.1.4 ..... */
  15. #ifndef COMPRESSED_UBOOT
  16.         checkboard,   /* 显示 AP99 (ar7241 - Virian) U-boot */
  17.         init_func_ram,    /* 初始化内存 */
  18. #endif
  19.         NULL,
  20. };
复制代码

以上为初始化函数列表,依次运行

在初始化完成后,board_init_f 调用 relocate_code 将 U-Boot 代码从 Flash 中复制到内存中,再从内存中执行

回到 cpu/mips/start.S

  1.         .globl        relocate_code
  2.         .ent        relocate_code
  3. relocate_code:
  4.         move        sp, a0                /* Set new stack pointer                */

  5.         li        t0, CFG_MONITOR_BASE
  6.         la        t3, in_ram
  7.         lw        t2, -12(t3)        /* t2 <-- uboot_end_data        */
  8.         move        t1, a2

  9.         /*
  10.          * Fix GOT pointer:
  11.          *
  12.          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
  13.          */
  14.         /* 根据传递的参数计算移动距离 */
  15.         move        t6, gp
  16.         sub        gp, CFG_MONITOR_BASE
  17.         add        gp, a2                        /* gp now adjusted                */
  18.         sub        t6, gp, t6                /* t6 <-- relocation offset        */

  19.         /*
  20.          * t0 = source address
  21.          * t1 = target address
  22.          * t2 = source end address
  23.          */
  24.         /* 复制代码到内存 */
  25. 1:
  26.         lw        t3, 0(t0)
  27.         sw        t3, 0(t1)
  28.         addu        t0, 4
  29.         ble        t0, t2, 1b
  30.         addu        t1, 4                        /* delay slot                        */

  31.         /* If caches were enabled, we would have to flush them here.
  32.          */

  33.         /* Jump to where we've relocated ourselves.
  34.          */
  35.         /* 跳转到移动后的代码继续执行 */
  36.         addi        t0, a2, in_ram - _start
  37.         j        t0
  38.         nop

  39.         .word        uboot_end_data
  40.         .word        uboot_end
  41.         .word        num_got_entries

  42. in_ram:
  43.         /* 此时已经在内存中了 */
  44.         /* Now we want to update GOT.
  45.          */
  46.         lw        t3, -4(t0)        /* t3 <-- num_got_entries        */
  47.         addi        t4, gp, 8        /* Skipping first two entries.        */
  48.         li        t2, 2
  49.         /* GOT 表重定位 */
  50. 1:
  51.         lw        t1, 0(t4)
  52.         beqz        t1, 2f
  53.         add        t1, t6
  54.         sw        t1, 0(t4)
  55. 2:
  56.         addi        t2, 1
  57.         blt        t2, t3, 1b
  58.         addi        t4, 4                /* delay slot                        */

  59.         /* Clear BSS.
  60.          */
  61.         lw        t1, -12(t0)        /* t1 <-- uboot_end_data        */
  62.         lw        t2, -8(t0)        /* t2 <-- uboot_end                */
  63.         add        t1, t6                /* adjust pointers                */
  64.         add        t2, t6

  65.         /* 清除 BSS 段,即全局变量清零 */
  66.         sub        t1, 4
  67. 1:        addi        t1, 4
  68.         bltl        t1, t2, 1b
  69.         sw        zero, 0(t1)        /* delay slot                        */

  70.         /* 移交控制权到 board_init_r */
  71.         move        a0, a1
  72.         la        t9, board_init_r
  73.         j        t9
  74.         move        a1, a2                /* delay slot                        */

  75.         .end        relocate_code
复制代码

relocate_code 的作用是将 U-Boot 代码移动到内存的最高端,并清空 BSS 段,设置栈指针,创造一个完整的 C 环境。

然后 C 环境就绪,进入 board_init_r 继续运行,此时 SPI Flash 不再被使用,U-Boot 完全在内存中运行了

回到 lib_mips/board.c:

  1. void board_init_r (gd_t *id, ulong dest_addr)
  2. {
  3.         cmd_tbl_t *cmdtp;
  4.         ulong size;
  5.         extern void malloc_bin_reloc (void);
  6. #ifndef CFG_ENV_IS_NOWHERE
  7.         extern char * env_name_spec;
  8. #endif
  9.         char *s, *e;
  10.         bd_t *bd;
  11.         int i;

  12.         gd = id;
  13.         gd->flags |= GD_FLG_RELOC;        /* tell others: relocation done */

  14.         debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);

  15.         gd->reloc_off = dest_addr - CFG_MONITOR_BASE;  /* 记录 U-Boot 重定位时移动的偏移量 */

  16.         monitor_flash_len = (ulong)&uboot_end_data - dest_addr;

  17.         /*
  18.          * We have to relocate the command table manually
  19.          */
  20.         /* U-Boot 命令表,重定位所有字符串地址和函数地址 */
  21.          for (cmdtp = &__u_boot_cmd_start; cmdtp !=  &__u_boot_cmd_end; cmdtp++) {
  22.                 ulong addr;

  23.                 addr = (ulong) (cmdtp->cmd) + gd->reloc_off;
  24. #if 0
  25.                 printf ("Command \"%s\": 0x%08lx => 0x%08lx\n",
  26.                                 cmdtp->name, (ulong) (cmdtp->cmd), addr);
  27. #endif
  28.                 cmdtp->cmd =
  29.                         (int (*)(struct cmd_tbl_s *, int, int, char *[]))addr;

  30.                 addr = (ulong)(cmdtp->name) + gd->reloc_off;
  31.                 cmdtp->name = (char *)addr;

  32.                 if (cmdtp->usage) {
  33.                         addr = (ulong)(cmdtp->usage) + gd->reloc_off;
  34.                         cmdtp->usage = (char *)addr;
  35.                 }
  36. #ifdef        CFG_LONGHELP
  37.                 if (cmdtp->help) {
  38.                         addr = (ulong)(cmdtp->help) + gd->reloc_off;
  39.                         cmdtp->help = (char *)addr;
  40.                 }
  41. #endif
  42.         }
  43.         /* there are some other pointer constants we must deal with */
  44. #ifndef CFG_ENV_IS_NOWHERE
  45.         env_name_spec += gd->reloc_off;
  46. #endif

  47.         /* 熄灭路由的 LED */
  48.         /* turn off switch LED added by tiger 20091225 */
  49.         ar7240_gpio_sw_led();

  50. ----------------------------------------------------省略----------------------------------------------------

  51.         /* configure available FLASH banks */
  52.         /* 初始化 Flash,显示 Flash:XXXX (X MB) */
  53.         size = flash_init();
  54.         display_flash_config (size);

  55.         bd = gd->bd;
  56.         bd->bi_flashstart = CFG_FLASH_BASE;
  57.         bd->bi_flashsize = size;
  58. #if CFG_MONITOR_BASE == CFG_FLASH_BASE
  59.         bd->bi_flashoffset = monitor_flash_len;        /* reserved area for U-Boot */
  60. #else
  61.         bd->bi_flashoffset = 0;
  62. #endif

  63.         /* initialize malloc() area */
  64.         /* 初始化内存管理器,以便能够使用 malloc 等函数 */
  65.         mem_malloc_init();
  66.         malloc_bin_reloc();

  67.         /* relocate environment function pointers etc. */
  68.         /* 重定位环境变量相关函数和数据 */
  69.         env_relocate();

  70.         /* board MAC address */
  71.         s = getenv ("ethaddr");
  72.         for (i = 0; i < 6; ++i) {
  73.                 bd->bi_enetaddr[i] = s ? simple_strtoul (s, &e, 16) : 0;
  74.                 if (s)
  75.                         s = (*e) ? e + 1 : e;
  76.         }

  77.         /* IP Address */
  78.         bd->bi_ip_addr = getenv_IPaddr("ipaddr");

  79. #if defined(CONFIG_PCI)
  80.         /*
  81.          * Do pci configuration
  82.          */
  83.         /* PCI 设备初始化 */
  84.         pci_init();
  85. #endif

  86. /** leave this here (after malloc(), environment and PCI are working) **/
  87.         /* Initialize devices */
  88.         devices_init ();

  89.         jumptable_init ();

  90.         /* Initialize the console (after the relocation and devices init) */
  91.         console_init_r ();
  92. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/

  93.         /* Initialize from environment */
  94.         if ((s = getenv ("loadaddr")) != NULL) {
  95.                 load_addr = simple_strtoul (s, NULL, 16);
  96.         }
  97. #if (CONFIG_COMMANDS & CFG_CMD_NET)
  98.         if ((s = getenv ("bootfile")) != NULL) {
  99.                 copy_filename (BootFile, s, sizeof (BootFile));
  100.         }
  101. #endif        /* CFG_CMD_NET */

  102. #if defined(CONFIG_MISC_INIT_R)
  103.         /* miscellaneous platform dependent initialisations */
  104.         misc_init_r ();
  105. #endif

  106. #if (CONFIG_COMMANDS & CFG_CMD_NET)
  107.         /* 初始化网络 */
  108. #if defined(CONFIG_NET_MULTI)
  109.         puts ("Net:   ");
  110. #endif
  111.         eth_initialize(gd->bd);
  112. #endif

  113.         /* main_loop() can return to retry autoboot, if so just run it again. */
  114.         /* 进入命令主循环,永不返回 */
  115.         for (;;) {
  116.                 main_loop ();
  117.         }

  118.         /* NOTREACHED - no way out of command loop except booting */
  119. }
复制代码

到此为止 U-Boot 就开始正常运行了
在处理交互命令前,U-Boot 会检查有没有启动命令

文件:common/main.c

  1. void main_loop (void)
  2. {
  3. ----------------------------------------------------省略----------------------------------------------------

  4. #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
  5.         char *s;
  6.         int bootdelay;
  7. #endif
  8. ----------------------------------------------------省略----------------------------------------------------

  9. #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
  10.         /* 获取启动延时 */
  11.         s = getenv ("bootdelay");
  12.         bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;

  13. //        debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);

  14. # ifdef CONFIG_BOOT_RETRY_TIME
  15.         init_cmd_timeout ();
  16. # endif        /* CONFIG_BOOT_RETRY_TIME */

  17. ----------------------------------------------------省略----------------------------------------------------

  18.                 /* 获取启动命令 */
  19.                 s = getenv ("bootcmd");
  20.        if (!s) {
  21.             /* 如果没有启动命令,就设置默认的命令 */
  22. #ifdef CONFIG_ROOTFS_FLASH
  23.            /* XXX if rootfs is in flash, expect uImage to be in flash */
  24. #ifdef CONFIG_AR7100
  25.            /* 这里设置的即为 AR71XX 的默认固件启动命令 */
  26.            setenv ("bootcmd", "bootm 0xbf200000");
  27. #else
  28.            setenv ("bootcmd", "bootm 0xbf450000");
  29. #endif /* CONFIG_AR7100 */
  30. #else
  31.            setenv ("bootcmd", "tftpboot 0x8022c090 uImage; bootm 0x8022c090");
  32. #endif
  33.        }
  34.                 /* 重新获取启动命令 */
  35.                 s = getenv ("bootcmd");

  36. //        debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");

  37.         if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
  38. # ifdef CONFIG_AUTOBOOT_KEYED
  39.                 int prev = disable_ctrlc(1);        /* disable Control C checking */
  40. # endif

  41. # ifndef CFG_HUSH_PARSER
  42.                 /* 执行启动命令 */
  43.                 run_command (s, 0);
  44. # else
  45.                 parse_string_outer(s, FLAG_PARSE_SEMICOLON |
  46.                                     FLAG_EXIT_FROM_LOOP);
  47. # endif

  48. # ifdef CONFIG_AUTOBOOT_KEYED
  49.                 disable_ctrlc(prev);        /* restore Control C checking */
  50. # endif
  51.         }

  52. ----------------------------------------------------省略----------------------------------------------------
  53. #endif        /* CONFIG_BOOTDELAY */

  54. #ifdef CONFIG_AMIGAONEG3SE
  55.         {
  56.             extern void video_banner(void);
  57.             video_banner();
  58.         }
  59. #endif

  60.         /* 启动命令执行完毕,则开始处理交互命令 */

  61.         /*
  62.          * Main Loop for Monitor Command Processing
  63.          */
  64. #ifdef CFG_HUSH_PARSER
  65.         parse_file_outer();
  66.         /* This point is never reached */
  67.         for (;;);
  68. #else
  69.         for (;;) {
  70. #ifdef CONFIG_BOOT_RETRY_TIME
  71.                 if (rc >= 0) {
  72.                         /* Saw enough of a valid command to
  73.                          * restart the timeout.
  74.                          */
  75.                         reset_cmd_timeout();
  76.                 }
  77. #endif
  78.                 len = readline (CFG_PROMPT);

  79.                 flag = 0;        /* assume no special flags for now */
  80.                 if (len > 0)
  81.                         strcpy (lastcommand, console_buffer);
  82.                 else if (len == 0)
  83.                         flag |= CMD_FLAG_REPEAT;
  84. #ifdef CONFIG_BOOT_RETRY_TIME
  85.                 else if (len == -2) {
  86.                         /* -2 means timed out, retry autoboot
  87.                          */
  88.                         puts ("\nTimed out waiting for command\n");
  89. # ifdef CONFIG_RESET_TO_RETRY
  90.                         /* Reinit board to run initialization code again */
  91.                         do_reset (NULL, 0, 0, NULL);
  92. # else
  93.                         return;                /* retry autoboot */
  94. # endif
  95.                 }
  96. #endif

  97.                 if (len == -1)
  98.                         puts ("<INTERRUPT>\n");
  99.                 else
  100.                         rc = run_command (lastcommand, flag);

  101.                 if (rc <= 0) {
  102.                         /* invalid command or not repeatable, forget it */
  103.                         lastcommand[0] = 0;
  104.                 }
  105.         }
  106. #endif /*CFG_HUSH_PARSER*/
  107. }
复制代码

至此,U-Boot 的启动流程就分析完毕了


相关代码位置:

AR7241 架构代码:

board/ar7240/ap99:
ap99.c 包含 USB 初始化等

board/ar7240/common:
ar7240_flash.c 包含 Flash 初始化代码
ar7240_pci.c 包含 PCI-E 设备初始化代码
ar7240_s26_phy.c:AR724X/AR9331 内置交换机初始化代码
lowlevel_init.S:lowlevel_init 函数所在的代码,用于初始化 CPU 频率

cpu/mips/ar7240:
ag7240.c:网络驱动
ar7240_serial.c:串口初始化及操作代码
meminit.c:内存初始化代码

U-Boot 通用代码:
common:
cmd_*.c: U-Boot 命令代码
env_*.c:环境变量底层模块
command.c:命令解释模块
console.c:控制台模块
dlmalloc.c:内存管理模块
environment.c:环境变量公用模块

net:
eth.c:网络初始化模块
net.c:网络功能实现及调度模块
tftp.c:tftp 功能模块

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多
    喜欢该文的人也喜欢 更多

    ×
    ×

    ¥.00

    微信或支付宝扫码支付:

    开通即同意《个图VIP服务协议》

    全部>>