u-boot程式碼分析

來源:互聯網
上載者:User

一、第1階段:arch/arm/arm920t/start.S1. 硬體初始化:1.1 把CPU切換到SVC32模式1.2 關看門狗1.3 屏蔽中斷1.4 初始化SDRAM2. 重定位代碼3. 跳轉到SDRAM去繼續執行3.1 設定棧3.2 清除BSS3.3 跳轉二、第2階段:從lib_arm/board.c: start_armboot函數分析1. 一系列的初始化:1.1 單板初始化:board_init (設定時鐘、GPIO、......)1.2 環境變數初始化:env_init (如果FLASH上有正確的環境變數,則用它;否則用預設的)1.3 "輸入輸出系統printf,scanf"初始化:init_baudrate、serial_init、console_init_f2. 其他組件的初始化2.1 NOR FLASH初始化:flash_init2.2 NAND FLASH初始化:nand_init2.3 網卡初始化:三、主迴圈    for (;;) {        main_loop ();    }1. 獲得bootdelay:    s = getenv ("bootdelay");    bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;2. 獲得"啟動命令"    s = getenv ("bootcmd"); // s="nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0"                                  "tftp 0x30007FC0 uImage; bootm 0x30007FC0"                                  " cp 10000000 0x30007FC0; bootm  "0x30007FC0 + 640x30008000    3. 倒數計時:abortbootif (bootdelay >= 0 && s && !abortboot (bootdelay)) {}4. 執行"啟動命令"     run_command (s, 0);  // 如果倒數期間沒有按下按鍵5. 如果第4步失敗,for (;;) {    len = readline (CFG_PROMPT);   // 從串口讀入一行資料,存在console_buffer    strcpy (lastcommand, console_buffer);    rc = run_command (lastcommand, flag);}   四、u-boot的核心:命令run_command    argc = parse_line (finaltoken, argv);  // "md.l 0" => argc = 2, argv[0]="md.l", argv[1]="0"    cmdtp = find_cmd(argv[0]);             // 根據"md.l"來找到"命令"    (cmdtp->cmd) (cmdtp, flag, argc, argv)    怎麼找到命令:find_cmd    len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd); // “md.l“ ==> len = 2    在__u_boot_cmd_start~__u_boot_cmd_end找出cmd_tbl_t,    if (strncmp (cmd, cmdtp->name, len) == 0) // 返回找到的cmd_tbl_t__u_boot_cmd_start、__u_boot_cmd_end在哪定義呢?在board/smdk2410/u-boot.lds裡有:    __u_boot_cmd_start = .;    .u_boot_cmd : { *(.u_boot_cmd) }    __u_boot_cmd_end = .;   在源碼裡搜"u_boot_cmd"Command.h (include):#define Struct_Section  __attribute__ ((unused,section (".u_boot_cmd")))#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}舉例:U_BOOT_CMD(    md, 3,  1,  do_mem_md,    "md  - memory display\n",    "[.b, .w, .l] address [# of objects]\n    - memory display\n");cmd_tbl_t __u_boot_cmd_md __attribute__ ((unused,section (".u_boot_cmd"))) = {"md", 3, 1, do_mem_md, "md  - memory display\n", "[.b, .w, .l] address [# of objects]\n    - memory display\n"}五、bootm命令分析:common/cmd_bootm.cdo_bootm : "bootm 31000000", argc=2, argv[0]="bootm", argv[1]="31000000"// 1. 讀取uImage的頭部,獲得資訊:載入地址、入口地址、長度、作業系統類型、是否壓縮/* get kernel image header, start address and length */// os_data = 0x31000000+64; os_len = 0x902d1c00os_hdr = boot_get_kernel (cmdtp, flag, argc, argv,&images, &os_data, &os_len);img_addr = simple_strtoul(argv[1], NULL, 16); //img_addr=0x31000000*os_data = *os_len = 0;switch (genimg_get_format ((void *)img_addr)) {hdr = (image_header_t *)img_addr;if (image_check_magic(hdr)){format = IMAGE_FORMAT_LEGACY;}case IMAGE_FORMAT_LEGACY:// 作一些檢查,比如CRC// hdr = img_addr = 0x31000000hdr = image_get_kernel (img_addr, images->verify);switch (image_get_type (hdr)) {case IH_TYPE_KERNEL:// *os_data = hdr+sizeof(hdr) = 0x31000000+64*os_data = image_get_data (hdr);// *os_len = 0x902d1c00*os_len = image_get_data_size (hdr);}// 把頭部拷到全域變數裡去memmove (&images->legacy_hdr_os_copy, hdr, sizeof(image_header_t));}/* get image parameters */switch (genimg_get_format (os_hdr)) {case IMAGE_FORMAT_LEGACY:type = image_get_type (os_hdr);comp = image_get_comp (os_hdr);os = image_get_os (os_hdr);image_end = image_get_image_end (os_hdr);load_start = image_get_load (os_hdr);break;    // 2. 把核心移到載入地址去:移到哪、移多大?這些資訊存在uImage的頭部: uImage = 頭部+真正的核心(zImage等)switch (comp) {case IH_COMP_NONE:if (load_start == (ulong)(os_hdr+sizeof(image_header_t))) {printf ("   XIP %s ... ", type_name);} else {printf ("   Loading %s ... ", type_name);            /* 如果當前真正的核心不位於uImage頭部指示的載入地址             * 移動             */memmove_wd ((void *)load_start,   (void *)os_data, os_len, CHUNKSZ);}// 3. 根據核心的類型調用不同的處理函數switch (os) {default:/* handled by (original) Linux case */case IH_OS_LINUX:do_bootm_linux (cmdtp, flag, argc, argv, &images); // Bootm.c (lib_arm)// 4. 設定參數:把參數存在雙方定死的位置intmachid = bd->bi_arch_number; // MACH_TYPE_SMDK2410,193void(*theKernel)(int zero, int arch, uint params);#ifdef CONFIG_CMDLINE_TAGchar *commandline = getenv ("bootargs"); /* 傳給核心的命令列參數 */#endifep = image_get_ep (&images->legacy_hdr_os_copy); // 0x30008000theKernel = (void (*)(int, int, uint))ep; // 0x30008000s = getenv ("machid");machid = simple_strtoul (s, NULL, 16);/* 把參數存在雙方定死的位置 */setup_start_tag (bd);setup_memory_tags (bd);char *commandline = getenv ("bootargs");setup_commandline_tag (bd, commandline);  /* root=/dev/mtdblock3 console=ttySAC0,115200 */setup_end_tag (bd);// 5. 啟動:跳到核心的入口地址theKernel (0, machid, bd->bi_boot_params);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.