Linux内核启动:setup_arch

2024-04-16 07:48
文章标签 linux 启动 内核 setup arch

本文主要是介绍Linux内核启动:setup_arch,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

BootLoader 可以向Linux 传递参数,编译内核时也可以配置boot options

调试中使用的U-Boot bootargs如下:

noinitrd root=/dev/mtdblock3 rw console=ttySAC0,115200 init=/linuxrc mem=64M

内核版本:

2.6.35.7

内核的处理参数的整体过程如下:

u-boot将配置参数地址通过寄存器传递给内核

内核(arch/arm/kernel/head-common.S中的 __mmap_switched)将这个地址存入__atags_pointer(定义于arch/arm/kernel/setup.c)

setup_arch() 函数

[html] view plain copy print ?
  1. <span style="font-size: 14px;">void __init setup_arch(char **cmdline_p)  
  2.   
  3. {  
  4.          struct tag *tags = (struct tag *)&init_tags;  
  5.          struct machine_desc *mdesc;  
  6.          char *from = default_command_line; 编译内核时配置的Boot Options  
  7.   
  8.   
  9.          unwind_init();  
  10.   
  11.   
  12.          setup_processor();  
  13.          mdesc = setup_machine(machine_arch_type);  
  14.          machine_name = mdesc->name;  
  15.   
  16.    
  17.          if (mdesc->soft_reboot)  
  18.                    reboot_setup("s");  
  19.   
  20.    
  21.          if (__atags_pointer)                                               检查BootLoader是否传入参数  
  22.                    tags = phys_to_virt(__atags_pointer);  
  23.          else if (mdesc->boot_params)  
  24.                    tags = phys_to_virt(mdesc->boot_params);  machine descriptor中传入的启动参数地址(arch/arm/mach-s3c2440/mach-mini2440.c)  
  25.   
  26.    
  27.          /*  
  28.           * If we have the old style parameters, convert them to  
  29.           * a tag list.  
  30.           */  
  31.          if (tags->hdr.tag != ATAG_CORE)  
  32.                    convert_to_tag_list(tags);  
  33.          if (tags->hdr.tag != ATAG_CORE)  
  34.                    tags = (struct tag *)&init_tags;       使用default init_tags,其中内存的定义是: 起始地址:0x30000000,大小是16M  
  35.   
  36.    
  37.          if (mdesc->fixup)  
  38.                    mdesc->fixup(mdesc, tags, &from, &meminfo);  
  39.   
  40.    
  41.          if (tags->hdr.tag == ATAG_CORE) {  
  42.                    if (meminfo.nr_banks != 0)                如果内存已经初始化,则忽略mem TAG  
  43.                             squash_mem_tags(tags);  
  44.                    save_atags(tags);  
  45.                    parse_tags(tags);             解析TAGS,其中如果U-boot传入ATAG_CMDLINE,则使用U-boot传入的bootargs覆盖default_command_line  
  46.          }  
  47.   
  48.    
  49.          init_mm.start_code = (unsigned long) _text;  
  50.          init_mm.end_code   = (unsigned long) _etext;  
  51.          init_mm.end_data   = (unsigned long) _edata;  
  52.          init_mm.brk        = (unsigned long) _end;  
  53.   
  54.    
  55.          /* parse_early_param needs a boot_command_line */  
  56.          strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);         将defualt_command_line拷入boot_command_line  
  57.    
  58.   
  59.          /* populate cmd_line too for later use, preserving boot_command_line */  
  60.          strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);  
  61.          *cmdline_p = cmd_line;  
  62.   
  63.    
  64.          parse_early_param();               大部分参数的early属性为0,即大部分参数在早期不处理,如noinitrd,console等  
  65.   
  66.    
  67.          paging_init(mdesc);  
  68.          request_standard_resources(&meminfo, mdesc);  
  69.   
  70.           
  71.          ***************  
  72. </span>  
  73. }  
void __init setup_arch(char **cmdline_p){struct tag *tags = (struct tag *)&init_tags;struct machine_desc *mdesc;char *from = default_command_line; 编译内核时配置的Boot Optionsunwind_init();setup_processor();mdesc = setup_machine(machine_arch_type);machine_name = mdesc->name;if (mdesc->soft_reboot)reboot_setup("s");if (__atags_pointer)                                               检查BootLoader是否传入参数tags = phys_to_virt(__atags_pointer);else if (mdesc->boot_params)tags = phys_to_virt(mdesc->boot_params);  machine descriptor中传入的启动参数地址(arch/arm/mach-s3c2440/mach-mini2440.c)/** If we have the old style parameters, convert them to* a tag list.*/if (tags->hdr.tag != ATAG_CORE)convert_to_tag_list(tags);if (tags->hdr.tag != ATAG_CORE)tags = (struct tag *)&init_tags;       使用default init_tags,其中内存的定义是: 起始地址:0x30000000,大小是16Mif (mdesc->fixup)mdesc->fixup(mdesc, tags, &from, &meminfo);if (tags->hdr.tag == ATAG_CORE) {if (meminfo.nr_banks != 0)                如果内存已经初始化,则忽略mem TAGsquash_mem_tags(tags);save_atags(tags);parse_tags(tags);             解析TAGS,其中如果U-boot传入ATAG_CMDLINE,则使用U-boot传入的bootargs覆盖default_command_line}init_mm.start_code = (unsigned long) _text;init_mm.end_code   = (unsigned long) _etext;init_mm.end_data   = (unsigned long) _edata;init_mm.brk        = (unsigned long) _end;/* parse_early_param needs a boot_command_line */strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);         将defualt_command_line拷入boot_command_line/* populate cmd_line too for later use, preserving boot_command_line */strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);*cmdline_p = cmd_line;parse_early_param();               大部分参数的early属性为0,即大部分参数在早期不处理,如noinitrd,console等paging_init(mdesc);request_standard_resources(&meminfo, mdesc);***************

}


一.u-boot传递TAG到kernel的解析

       在setup_arch函数的parse_tags中对传递过来的TAGLIST进行了解析

       对每一项的tag使用parse_tag分析,

       for (t = &__tagtable_begin; t < &__tagtable_end; t++)

              if (tag->hdr.tag == t->tag) {

                     t->parse(tag);

                     break;

              }

       其中__tagtable_begin,__tagtable_end在vmlinux.ld中也有定义,这里看tagtable的建立过程

       #define __tagtalbe(tag,fn)/

       Static struct tagtable __tagtable_##fn __tag={tag,fn}

       #define __tag __userd __attribute__((__section__(“.taglist.init”)))

对于上述宏中的fn,就是tagtable结构中的parse指针所指向的函数。

       而在setup.c中,已经通过__tagtalbe(ATAG_XXX,XXX)建立起所有可能的tagtable,所以可以通过遍历__tagtable_begin~__tagtable_end找到对应的tagtable,并调用对应的parse进行解析并配置


这篇关于Linux内核启动:setup_arch的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/908194

相关文章

windows和Linux使用命令行计算文件的MD5值

《windows和Linux使用命令行计算文件的MD5值》在Windows和Linux系统中,您可以使用命令行(终端或命令提示符)来计算文件的MD5值,文章介绍了在Windows和Linux/macO... 目录在Windows上:在linux或MACOS上:总结在Windows上:可以使用certuti

Linux之systemV共享内存方式

《Linux之systemV共享内存方式》:本文主要介绍Linux之systemV共享内存方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、工作原理二、系统调用接口1、申请共享内存(一)key的获取(二)共享内存的申请2、将共享内存段连接到进程地址空间3、将

快速修复一个Panic的Linux内核的技巧

《快速修复一个Panic的Linux内核的技巧》Linux系统中运行了不当的mkinitcpio操作导致内核文件不能正常工作,重启的时候,内核启动中止于Panic状态,该怎么解决这个问题呢?下面我们就... 感谢China编程(www.chinasem.cn)网友 鸢一雨音 的投稿写这篇文章是有原因的。为了配置完

Linux命令之firewalld的用法

《Linux命令之firewalld的用法》:本文主要介绍Linux命令之firewalld的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux命令之firewalld1、程序包2、启动firewalld3、配置文件4、firewalld规则定义的九大

Linux之计划任务和调度命令at/cron详解

《Linux之计划任务和调度命令at/cron详解》:本文主要介绍Linux之计划任务和调度命令at/cron的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux计划任务和调度命令at/cron一、计划任务二、命令{at}介绍三、命令语法及功能 :at

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

kali linux 无法登录root的问题及解决方法

《kalilinux无法登录root的问题及解决方法》:本文主要介绍kalilinux无法登录root的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录kali linux 无法登录root1、问题描述1.1、本地登录root1.2、ssh远程登录root2、

Linux ls命令操作详解

《Linuxls命令操作详解》通过ls命令,我们可以查看指定目录下的文件和子目录,并结合不同的选项获取详细的文件信息,如权限、大小、修改时间等,:本文主要介绍Linuxls命令详解,需要的朋友可... 目录1. 命令简介2. 命令的基本语法和用法2.1 语法格式2.2 使用示例2.2.1 列出当前目录下的文

Redis在windows环境下如何启动

《Redis在windows环境下如何启动》:本文主要介绍Redis在windows环境下如何启动的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Redis在Windows环境下启动1.在redis的安装目录下2.输入·redis-server.exe