发 帖  
[问答]

自己写u-boot启动不了内核?请问是为什么?

2837 韦东山 u-boot

21.myboot.zip

78.46 KB , 下载次数: 9

奖励3积分
2019-10-11 01:10:03   评论 分享淘帖 邀请回答 举报
1个回答
2019-10-11 01:10:04 11 评论

举报

11 条评论
  • 2019-10-11 12:48

    可能我描述得不够清楚。 我希望通过运行自己编写的简单u-boot来启动内核。问题是在完成内核从nand拷贝到sdram,设置环境变量后, 跳转到sdram中内核的起始地址时,内核并没有启动。也就是说运行到如下代码后,卡死了。
    /* 3. 跳转到内核 */

    putstr("Starting kernel...\r\n");

    theKernel = (void (*)(int, int, unsigned int)) 0x50008000;  //内核在sdram中的地址
    theKernel(0, 2520, 0x50000100);  //机器ID: 2520,  内核参数约定地址:0x50000100

    李存皓 回复 万飞: 2019-10-11 13:59

    请问下你是怎么确定卡死的?就因为没有串口输出就觉得是卡死了?
    出现这个问题,需要分析为什么,我上面提出的方法就是我个人的思路,去解决问题,我也没从你的代码中发现什么错误,所以需要深入调查,你开发板提供的uboot可能没有给你源码,你自己写的uboot是否能正常加载内核需要深入调查一下
    是否内核中需要的内核参数格式和你代码中的参数格式一致?有没有其它认证相关?
    首先我从代码看没有看出问题,现在问题是没有串口输出,那么是内核还没有启动到串口输出那里就失败了,还是内核根本没启动?我觉得你应该验证这些问题

    万飞 回复 李存皓: 2019-10-11 14:12

    谢谢你的回答! 现在可以明确的是内核没有启动,因为使用友善官方提供的u-boot启动内核时,最开始会执行解压操作,串口会提示“Uncompressing...”。而我的代码都没有执行内核的解压。 您的意思时很有可能问题出在内核参数上?

    李存皓 回复 万飞: 2019-10-11 14:22

    你用的是zImage?uBoot支持zImage启动内核吗?这个是压缩文件
    你可以从这里检查一下,是否需要用uImage或者在uboot里面解压zImage再copy给sdram?

    李存皓 回复 万飞: 2019-10-11 14:39

    你应该知道uboot里面有个bootm函数,可以了解一下,首先要获取zImage,然后解压,然后获取image的header info,找到第一个指令地址,这个地址才是theKernel的地址,我估计你就是这里有问题

    万飞 回复 李存皓: 2019-10-11 14:57

    好的,谢谢你! 我用的是友善之臂提供的linux内核的zImage映像文件,还没有看它的源文件,linux内核还没研究过,不知道从哪个地方看这个header info... 分数就先给你吧。

    万飞 回复 李存皓: 2019-10-11 15:00

    既然uboot启动不了zImage,那么为什么友善之臂提供的u-boot能够启动?

    李存皓 回复 万飞: 2019-10-11 15:03

    我的意思就是你开发板的uboot肯定是解压了zImage然后在解压后的image中找到了image的info,然后找到了入口,thekernel再定位到这个入口,现在的uboot版本里面这些都做的挺好的了,你查看下uboot源码里面的bootm.c文件就清除了

    万飞 回复 李存皓: 2019-10-12 01:22

    看了一下友善的u-boot源码,在do_bootm()函数中有对zImage启动的支持:

    #define LINUX_ZIMAGE_MAGIC        0x016f2818
            if (*(ulong *)(addr + 9*4) == LINUX_ZIMAGE_MAGIC) {
                    printf("Boot with zImage\n");
                    addr = virt_to_phys(addr);
                    hdr->ih_os = IH_OS_LINUX;
                    hdr->ih_ep = ntohl(addr);
                    goto after_header_check;
            }
    #endif

    然后跳转到after_header_check处执行,一系列判断后,跳转到do_bootm_linux()函数执行。 检查了一下这个do_bootm_linux()函数,主要做的工作就是设置内核参数(tags),然后跳转到内核入口地址启动内核:

    setup_start_tag (bd);
    #ifdef CONFIG_SERIAL_TAG
            setup_serial_tag (&params);
    #endif
    #ifdef CONFIG_REVISION_TAG
            setup_revision_tag (&params);
    #endif
    #ifdef CONFIG_SETUP_MEMORY_TAGS
            setup_memory_tags (bd);
    #endif
    #ifdef CONFIG_CMDLINE_TAG
            setup_commandline_tag (bd, commandline);
    #endif
    #ifdef CONFIG_INITRD_TAG
            if (initrd_start && initrd_end)
                    setup_initrd_tag (bd, initrd_start, initrd_end);
    #endif
    #if defined (CONFIG_VFD) || defined (CONFIG_LCD)
            setup_videolfb_tag ((gd_t *) gd);
    #endif
            setup_end_tag (bd);
    #endif

            /* we assume that the kernel is in place */
            printf ("\nStarting kernel ...\n\n");

    #ifdef CONFIG_USB_DEVICE
            {
                    extern void udc_disconnect (void);
                    udc_disconnect ();
            }
    #endif

            cleanup_before_linux ();

            theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
    }

    这个与我写的代码完成的工作是一样的啊? 为什么我的就不能启动zImage内核呢?

    网上查了一下,uImage只是比zImage多了64字节的头部,真正的内核还是zImage,而且zImage是可以完成自解压的。

    还请不吝赐教,谢谢!!

    李存皓 回复 万飞: 2019-10-12 09:03

    你自己写的uboot,theKernel的地址就是你copy的uImage到sdram的地址,而实际thekernel的地址应该不是,你看uBoot源码里面,theKernel的地址是怎么设置的就清除了,我估计你的uboot就是出现在theKernel地址的问题

    万飞 回复 李存皓: 2019-10-12 21:38

    我看韦东山自己写uboot时,theKernel的入口地址就是等于下载地址啊?而且u-boot源码里面好像也是这样的:

    if (argc < 2) {
                    addr = load_addr;
            } else {
                    addr = simple_strtoul(argv[1], NULL, 16);
            }

    #ifdef CONFIG_ZIMAGE_BOOT
    #define LINUX_ZIMAGE_MAGIC        0x016f2818
            if (*(ulong *)(addr + 9*4) == LINUX_ZIMAGE_MAGIC) {
                    printf("Boot with zImage\n");
                    addr = virt_to_phys(addr);
                    hdr->ih_os = IH_OS_LINUX;
                    hdr->ih_ep = ntohl(addr);
                    goto after_header_check;
            }
    #endif

    从上面的代码可以看到,hdr->ih_ep = ntohl(addr), 表示内核的入口地址就是等于内核的下载地址。

    void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
                         ulong addr, ulong *len_ptr, int verify)
    {
            ulong len = 0, checksum;
            ulong initrd_start, initrd_end;
            ulong data;
            void (*theKernel)(int zero, int arch, uint params);
            image_header_t *hdr = &header;
            bd_t *bd = gd->bd;

    #ifdef CONFIG_CMDLINE_TAG
            char *commandline = getenv ("bootargs");
    #endif

            theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);

    从上面的代码可以看到, theKernel的地址 = ntohl(hdr->ih_ep), 将hdr->ih_ep = ntohl(addr) 代入, 得到theKernel的地址 = addr = load_addr。

    这不是表明内核的入口地址就等于内核的下载地址吗?  至于为什么能相等,我也不清楚,因为对内核的启动机制没有研究...

    请赐教!谢谢!

撰写答案

你正在撰写答案

如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。

您需要登录后才可以回帖 登录/注册

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
快速回复 返回顶部 返回列表
关注微信公众号

电子发烧友网

电子发烧友论坛

社区合作
刘勇
联系电话:15994832713
邮箱地址:liuyong@huaqiu.com
社区管理
elecfans短短
微信:elecfans_666
邮箱:users@huaqiu.com
关闭

站长推荐 上一条 /6 下一条

快速回复 返回顶部 返回列表