Linux运维知识之linux4.10.8 内核移植(一)---环境搭建及适配单板
小标 2018-12-07 来源 : 阅读 1644 评论 0

摘要:本文主要向大家介绍了Linux运维知识之linux4.10.8 内核移植(一)---环境搭建及适配单板,通过具体的内容向大家展现,希望对大家学习Linux运维知识有所帮助。

本文主要向大家介绍了Linux运维知识之linux4.10.8 内核移植(一)---环境搭建及适配单板,通过具体的内容向大家展现,希望对大家学习Linux运维知识有所帮助。

一、环境搭建
  源码包下载:git clone https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.10.8.tar.gz
  或者直接去kernel.org上面进行下载。
  交叉编译工具链制作:
  这个已经在u-boot移植中已经做过了://www.cnblogs.com/kele-dad/p/6910040.html
二、内核启动过程
2.1 Windows 和 Linux 系统的启动区别
  
  由bootloader确定启动哪块单板。
2.2 修改makefile
  下面的行注释掉:
  
  修改ARCH:
  
  修改交叉编译工具链:
  
2.3 选择默认配置
  找到默认配置:
  
  
  进入arm架构中:
  
  可以看到我们的架构中有 mini2440的架构,同时也有s3c2410的配置文件。
  进入内核根目录,配置成2410:
  
  打开.config 文件
  
  查看CPU,可以看到有2440的CPU:
  
  同时也支持 mini2440 的单板:
  
2.4 编译
   执行:make uImage
  进行编译:
  
  编译提示错误,那是因为没有安装u-boot 依赖包。
  
  提示要安装新包
  
  再执行编译:
  
  编译成功。
 2.5 烧写
  通过nfs进行烧写,nfs配置如文档://www.cnblogs.com/kele-dad/p/7082765.html
  
  启动内核:bootm 32000000
  
  看一下打印信息,有条错误,无法识别机器ID。下面打印出来了很多机器ID。
  现在我们要根据我们的机器ID 去u-boot 源码中看一下启动内核的代码了。
  进入Cmd_bootm.c (common),搜索bootm,找到下面这行代码:
  
  上面代码调用了 do_bootm 函数,进入函数中查看: 

 1 U_BOOT_CMD
 2     do_bootm
 3         do_bootm_subcommand
 4             do_bootm_subcommand
 5                 do_bootm_states
 6                     boot_os_fn *boot_fn;
 7                     bootm_start
 8                     bootm_find_os
 9                     bootm_find_other
10                     bootm_load_os
11                     boot_fn = bootm_os_get_boot_func(images->os.os);
12         do_bootm_states

  在do_bootm_states 中有一个结构体,boot_os_fn:

 1 static boot_os_fn *boot_os[] = {
 2     [IH_OS_U_BOOT] = do_bootm_standalone,
 3 #ifdef CONFIG_BOOTM_LINUX
 4     [IH_OS_LINUX] = do_bootm_linux,
 5 #endif
 6 #ifdef CONFIG_BOOTM_NETBSD
 7     [IH_OS_NETBSD] = do_bootm_netbsd,
 8 #endif
 9 #ifdef CONFIG_LYNXKDI
10     [IH_OS_LYNXOS] = do_bootm_lynxkdi,
11 #endif
12 #ifdef CONFIG_BOOTM_RTEMS
13     [IH_OS_RTEMS] = do_bootm_rtems,
14 #endif
15 #if defined(CONFIG_BOOTM_OSE)
16     [IH_OS_OSE] = do_bootm_ose,
17 #endif
18 #if defined(CONFIG_BOOTM_PLAN9)
19     [IH_OS_PLAN9] = do_bootm_plan9,
20 #endif
21 #if defined(CONFIG_BOOTM_VXWORKS) && 22     (defined(CONFIG_PPC) || defined(CONFIG_ARM))
23     [IH_OS_VXWORKS] = do_bootm_vxworks,
24 #endif
25 #if defined(CONFIG_CMD_ELF)
26     [IH_OS_QNX] = do_bootm_qnxelf,
27 #endif
28 #ifdef CONFIG_INTEGRITY
29     [IH_OS_INTEGRITY] = do_bootm_integrity,
30 #endif
31 #ifdef CONFIG_BOOTM_OPENRTOS
32     [IH_OS_OPENRTOS] = do_bootm_openrtos,
33 #endif
34 };

  在此结构体中调用的是 do_bootm_linux 函数,进入查看 Bootm.c (arch\arm\lib)

 1 int do_bootm_linux(int flag, int argc, char * const argv[],
 2            bootm_headers_t *images)
 3 {
 4     /* No need for those on ARM */
 5     if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
 6         return -1;
 7 
 8     if (flag & BOOTM_STATE_OS_PREP) {
 9         boot_prep_linux(images);
10         return 0;
11     }
12 
13     if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
14         boot_jump_linux(images, flag);
15         return 0;
16     }
17 
18     boot_prep_linux(images);
19     boot_jump_linux(images, flag);
20     return 0;
21 }

  在最后一句中执行 boot_jump_linux 函数:

 1 /* Subcommand: GO */
 2 static void boot_jump_linux(bootm_headers_t *images, int flag)
 3 {
 4     unsigned long machid = gd->bd->bi_arch_number;
 5     char *s;
 6     void (*kernel_entry)(int zero, int arch, uint params);
 7     unsigned long r2;
 8     int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
 9 
10     kernel_entry = (void (*)(int, int, uint))images->ep;
11 
12     s = getenv("machid");
13     if (s) {
14         if (strict_strtoul(s, 16, &machid) < 0) {
15             debug("strict_strtoul failed!\n");
16             return;
17         }
18         printf("Using machid 0x%lx from environment\n", machid);
19     }
20     bootstage_mark(BOOTSTAGE_ID_RUN_OS);
21     announce_and_cleanup(fake);
22 
23     if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
24         r2 = (unsigned long)images->ft_addr;
25     else
26         r2 = gd->bd->bi_boot_params;
27 
28     if (!fake) {
29             kernel_entry(0, machid, r2);
30     }
31 }

  从环境变量中获取mach_id ,然后进入 kernel。如果没有从环境变量获取,就采用默认值,此函数的第一句就是默认值。看看默认值是多少。
  machid = gd->bd->bi_arch_number;
  在Jz2440.c (board\samsung\jz2440) 中 设置了默认ID:

 1 int board_init(void)
 2 {
 3     /* arch number of JZ2440 board */
 4     gd->bd->bi_arch_number = MACH_TYPE_JZ2440;
 5 
 6     /* adress of boot parameters */
 7     gd->bd->bi_boot_params = 0x30000100;
 8 
 9     icache_enable();
10     dcache_enable();
11 
12     return 0;
13 }

  同时在Board_f.c (common) 的 setup_machine中也有设置ID:

1 static int setup_machine(void)
2 {
3 #ifdef CONFIG_MACH_TYPE
4     gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
5 #endif
6     return 0;
7 }

  CONFIG_MACH_TYPE 这个宏我们没有设置。
  那么我们的上一个设置ID的函数是有效的。
  在Mach-types.h (arch\arm\include\asm) 中设置的ID为194。
  
  然后在内核处,进入arch/arm/s3c24x0/ 目录,里面有很多我们的支持s3c24x0的板子,进入smdk2440的单板文件 mach-smdk2440.c:

MACHINE_START(S3C2440, "SMDK2440")
    /* Maintainer: Ben Dooks  */
    .atag_offset    = 0x100,

    .init_irq    = s3c2440_init_irq,
    .map_io        = smdk2440_map_io,
    .init_machine    = smdk2440_machine_init,
    .init_time    = smdk2440_init_time,
MACHINE_END

  在MACHINE_START中,就是根据mchine ID找到单板文件的。MACHINE_START的定义如下:
  
  展开后, .nr = MACH_TYPE_S3C2440,查找一下这个宏。
  
  generated 是临时生成的文件目录。可以看一下 mach-types.h:
  这是smdk2440的机器码
  
  这是mini2440的机器码
  
  可以对照我们的u-boot打印看出来:
  
  16进制转换成10进制就可以算出来了。
  根据以上的内容,我们可以在u-boot 中设置我们的 mach_id 的环境变量来启动内核,或者我们可以直接修改 u-boot 的默认ID值和这里的机器ID匹配即可。
  修改成mini2440的机器ID。直接修改u-boot源码:
  把mini2440改成如下:
  
  jz2440改成如下:
  
  这两个定义的机器码进行了对调而已。
  在 include/configs/jz2440.h 中设置启动参数,要加上波特率设置,否则会有乱码。mini2440的内核文件中设置的波特率为115200,smdk2440的为16M。
  
  然后编译烧写u-boot。
  进入u-boot 记得 print查看一下环境变量,如果 波特率没有改变过来 就重新设置一下:
  
  保存一下。然后烧入内核
   
  启动内核:
  
  已经有打印信息了。

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注系统运维Linux频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved