1 / 14

uCLinux 启动流程

uCLinux 启动流程. 徐远超 xuyuanchao@263.net http://xuyuanchao.ie.cnu.edu.cn. blob. Src/blob/start.S. Blob 代码分析. 第一阶段的代码在 start.s 中定义,大小为 l KB ,它包括从系统上电后在 0x00000000 地址开始执行的部分。 这部分代码运行在 Flash 中,它包括对 S3C44B0 的一些寄存器的初始化和将 Blob 第二阶段代码从 Flash 拷贝到 SDRAM 中。 除去第一阶段的 lKB 代码,剩下的部分都是第二阶段的代码。

zarifa
Download Presentation

uCLinux 启动流程

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. uCLinux启动流程 徐远超 xuyuanchao@263.net http://xuyuanchao.ie.cnu.edu.cn

  2. blob • Src/blob/start.S

  3. Blob代码分析 • 第一阶段的代码在start.s中定义,大小为l KB,它包括从系统上电后在0x00000000地址开始执行的部分。 • 这部分代码运行在Flash中,它包括对S3C44B0的一些寄存器的初始化和将Blob第二阶段代码从Flash拷贝到SDRAM 中。 • 除去第一阶段的lKB代码,剩下的部分都是第二阶段的代码。 • 第二阶段的起始文件为trampoline.s被复制到SDRAM后,就从第一阶段跳转到这个文件开始执行剩余部分代码。 • 第二阶段最大为63KB,单词trampoline词义为“蹦床”,所以在这个程序中进行一些BSS段设置,堆栈的初始化等工作后,最后跳转到main.c.

  4. relocate: • adr r0, _start • /* relocate the second stage loader */ • add r2, r0, #(64 * 1024) /* blob maximum size is 64kB */ • add r0, r0, #0x400 • ldr r1, BLOB_START • /* r0 = source address • * r1 = target address • * r2 = source end address • */ • copy_loop: • ldmia r0!, {r3-r10} • stmia r1!, {r3-r10} • cmp r0, r2 • ble copy_loop

  5. adr r0, real_vectors • add r2, r0, #1024 • ldr r1, =0x0c000000 • add r1, r1, #0x08 • vector_copy_loop: • ldmia r0!, {r3-r10} • stmia r1!, {r3-r10} • cmp r0, r2 • ble vector_copy_loop • /* turn off the LED. if it stays off it is an indication that • * we didn't make it into the C code • */ • /* bl led_off */ • /* blob is copied to ram, so jump to it */ • ldr r0, BLOB_START • mov pc, r0

  6. Trampoline.S • mrs r0, cpsr • bic r0, r0, #0x80 • msr cpsr, r0 • /* jump to C code */ • bl main • /* if main ever returns we just call it again */ • b _trampoline

  7. Main.c • /* wait 10 seconds before starting autoboot */ • SerialOutputString("Autoboot in progress, press any key to stop "); • for(i = 0; i < blob_status.boot_delay; i++) { • serial_write('.'); • retval = SerialInputBlock(commandline, 1, 1); • if(retval > 0) • break; • } • /* no key was pressed, so proceed booting the kernel */ • if(retval == 0) { • commandline[0] = '\0'; • parse_command("boot"); • }

  8. Linux.c • static int boot_linux(int argc, char *argv[]) • { • void (*theKernel)(int zero, int arch) = (void (*)(int, int))KERNEL_RAM_BASE; • clif(); • setup_start_tag(); • setup_memory_tags(); • setup_commandline_tag(argc, argv); • setup_initrd_tag(); • setup_ramdisk_tag(); • setup_end_tag(); • /* we assume that the kernel is in place */ • SerialOutputString("\nStarting kernel ...\n\n"); • serial_flush_output(); • /* disable subsystems that want to be disabled before kernel boot */ • exit_subsystems(); • /* start kernel */ • theKernel(0, ARCH_NUMBER); • SerialOutputString("Hey, the kernel returned! This should not happen.\n"); • return 0; • }

  9. 设置内核的启动参数 • Linux 2.4.x 以后的内核都期望以标记列表(tagged list)的形式来传递启动参数 • 启动参数标记列表以标记 ATAG_CORE 开始,以标记 ATAG_NONE 结束 • 每个标记由标识被传递参数的 tag_header 结构以及随后的参数值数据结构来组成 • 在嵌入式 Linux 系统中,通常需要由 Boot Loader 设置的常见启动参数有:ATAG_CORE、ATAG_MEM、ATAG_CMDLINE、ATAG_RAMDISK、ATAG_INITRD等.

  10. 直接跳转到内核的第一条指令处 • 在跳转时,下列条件要满足 • 1. CPU 寄存器的设置 • R0=0;@R1=机器类型 ID;@R2=启动参数标记列表在 RAM 中起始基地址 • 2. CPU 模式 • 必须禁止中断(IRQs和FIQs); • CPU 必须 SVC 模式; • 3. Cache 和 MMU 的设置 • MMU 必须关闭; • 指令 Cache 可以打开也可以关闭; • 数据 Cache 必须关闭.

  11. 内核解压缩 为了节省ROM空间,内核都是压缩过的,因此要有专门的解压缩程序解压缩内核。真正完成这个功能的函数是decompress_kernel(),该函数在文件misc.c中定义,其中misc.c在目录uClinux-2.4.x\arch\armnommu\boot\compressed中

  12. 解压后,跳转到解压后的地址处执行 • 该函数完成的功能包括处理器结构的初始化、中断的初始化、定时器的初始化、进程相关的初始化以及内存初始化等初始化工作完成内核初始化;最后内核创建一个init线程,在该线程中调用init进程,完成系统的启动。

  13. rest_init static void rest_init(void) { kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); //用kernel_thread建立了一个init进程,执行的是main.c中的init函数 unlock_kernel(); //内核解锁,不受保护 current->need_resched = 1; //该线程的标志位need_resched置位为1 cpu_idle(); //实现了进程init的被调度,从而函数init()被执行。 }

  14. Init函数 • 首先调用do_basic_setup()来完成外部设备以及驱动程的初始化,然后在函数调用完成后,init()会调用函数prepare_namespace()来登录root文件系统,并加载RAMDISK。接下来init()会调用函数free_initmem()来释放内核初始化函数所用的系统内存,并且打开/dev/console设备重新定向控制台,让系统调用execve来执行shell程序init。

More Related