浅析blob到kernel传递tags参数和cmdline处理流程

1 . blob
blob主程序main . c
int  main ( void )
{
     . . .
     /* initialise status */
    blob_status . paramType  =  fromFlash ;
    blob_status . kernelType  =  fromFlash ;
    blob_status . ramdiskType  =  fromFlash ;
    blob_status . downloadSpeed  =  baud_115200 ;
    blob_status . terminalSpeed  =  TERMINAL_SPEED ;
    blob_status . load_ramdisk  =  LOAD_RAMDISK ;
    blob_status . cmdline [ 0 ]   =   '\0' ;
    blob_status . boot_delay  =  BLOB_BOOT_DELAY_TIME ;
     . . .
}
static   void  setup_commandline_tag ( int  argc ,   char   * argv [ ] )
{
     . . .
     /* initialise commandline */
    params - > u . cmdline . cmdline [ 0 ]   =   '\0' ;

     /* copy default commandline from parameter block */
     if ( blob_status . cmdline [ 0 ]   ! =   '\0' )
        strlcpy ( params - > u . cmdline . cmdline ,  blob_status . cmdline ,
            COMMAND_LINE_SIZE ) ;

     /* copy commandline */
     if ( argc  > =  2 )   {
        p  =  params - > u . cmdline . cmdline ;

         for ( =  1 ;  i  <  argc ;  i + + )   {
            strlcpy ( p ,  argv [ i ] ,  COMMAND_LINE_SIZE ) ;
            p  + =   strlen ( p ) ;
             * p + +   =   ' ' ;
         }
         . . .
     }
     . . .
     if ( strlen ( params - > u . cmdline . cmdline )   >  0 )   {
        params - > hdr . tag  =  ATAG_CMDLINE ; //tag传递cmdline
        params - > hdr . size  =   ( sizeof ( struct  tag_header )   +
                  strlen ( params - > u . cmdline . cmdline )   +  1  +  4 )   > >  2 ;

        params  =  tag_next ( params ) ;
     }
}

static   int  boot_linux ( int  argc ,   char   * argv [ ] )
{
     . . .
    setup_start_tag ( ) ;
    setup_memory_tags ( ) ;
    setup_commandline_tag ( argc ,  argv ) ;
     . . .
    ramKernel ( 0 ,  mach_type ,  BOOT_PARAMS ) ;
     . . .
}
static   int  boot_linux ( int  argc ,   char   * argv [ ] )
{
     . . .
    ramKernel ( 0 ,  mach_type ,  BOOT_PARAMS ) ;
     . . .
}
static   void   ( * ramKernel ) ( int  zero ,   int  arch ,  u32 params )   =
     ( void   ( * ) ( int ,   int ,  u32 ) )  KERNEL_RAM_BASE ;
include / blob / arch / pxa_luther . h
# define  KERNEL_RAM_BASE         ( 0x80800000 ) //因为blob没有打开MMU,所以这里地址为DDR对应的物理地址
# define  BOOT_PARAMS          ( 0x80000100 ) //blob传递给kernel的tags物理存储地址,kenel会调用
所以ramKernel ( 0 ,  mach_type ,  BOOT_PARAMS ) ; 将跳转到
pc = 0x80800000处执行程序 ,
r0 = 0
r1 = mach_type
r2 = BOOT_PARAMS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2 . kernel
arch / arm / kernel / head . S
r0  =  0 ,
r1  =  machine nr ,  
r2  =  atags pointer .
     . section  ".text.head" ,   "ax"
     . type    stext ,   % function
ENTRY ( stext ) //(0xc0000000) + 0x00008000 kernel入口
    msr    cpsr_c ,   # PSR_F_BIT  |  PSR_I_BIT  |  SVC_MODE @ ensure svc mode
                        @  and  irqs disabled
    mrc    p15 ,  0 ,  r9 ,  c0 ,  c0        @ get processor id
    bl     __ lookup_processor_type        @ r5 = procinfo r9 = cpuid
    movs    r10 ,  r5                @ invalid processor  ( r5 = 0 ) ?
    beq     __ error_p            @ yes ,   error   'p'
    bl     __ lookup_machine_type        @ r5 = machinfo
    movs    r8 ,  r5                @ invalid machine  ( r5 = 0 ) ?
    beq     __ error_a            @ yes ,   error   'a'
    bl     __ vet_atags
    bl     __ create_page_tables

    ldr    r13 ,   __ switch_data        @ address to jump to after
                         @ the initialization is done
    adr    lr ,   __ after_proc_init        @  return   ( PIC )  address
    add    pc ,  r10 ,   # PROCINFO_INITFUNC //调用b    __arm920_setup
     . type     __ after_proc_init ,   % function
__ after_proc_init :
     . . .
    mov    pc ,  r13                @ clear the BSS  and  jump //跳转到__switch_data执行程序,即执行:__mmap_switched函数
arch / arm / mm / proc - arm920 . S
     . type     __ arm920_setup ,   # function
__ arm920_setup :
    mov    r0 ,   # 0
    mcr    p15 ,  0 ,  r0 ,  c7 ,  c7        @ invalidate I , D caches on v4
    mcr    p15 ,  0 ,  r0 ,  c7 ,  c10 ,  4        @ drain  write  buffer on v4
# ifdef  CONFIG_MMU
    mcr    p15 ,  0 ,  r0 ,  c8 ,  c7        @ invalidate I , D TLBs on v4
# endif
    adr    r5 ,  arm920_crval
    ldmia    r5 ,   { r5 ,  r6 }
    mrc    p15 ,  0 ,  r0 ,  c1 ,  c0        @ get control  register  v4
    bic    r0 ,  r0 ,  r5
    orr    r0 ,  r0 ,  r6
    mov    pc ,  lr //返回到__after_proc_init执行

arch / arm / kernel / head - common . S
ENTRY ( lookup_processor_type )
    stmfd      { r4  -  r7 ,  r9 ,  lr }
    mov    r9 ,  r0
    bl     __ lookup_processor_type //读取__proc_info_begin存储区的信息
    mov    r0 ,  r5
    ldmfd      { r4  -  r7 ,  r9 ,  pc }

     . long      __ proc_info_begin
     . long      __ proc_info_end

arch / arm / kernel / vmlinux . lds
   __ proc_info_begin  =   . ;
    * ( . proc . info . init )
   __ proc_info_end  =   . ;
比如:
arch / arm / mm / proc - arm920 . S
     . align

     . section  ".proc.info.init" ,   # alloc ,   # execinstr

     . type     __ arm920_proc_info , # object
__ arm920_proc_info :
     . long     0x41009200
     . long     0xff00fff0
     . long  PMD_TYPE_SECT  |  \
        PMD_SECT_BUFFERABLE  |  \
        PMD_SECT_CACHEABLE  |  \
        PMD_BIT4  |  \
        PMD_SECT_AP_WRITE  |  \
        PMD_SECT_AP_READ
     . long  PMD_TYPE_SECT  |  \
        PMD_BIT4  |  \
        PMD_SECT_AP_WRITE  |  \
        PMD_SECT_AP_READ
    b     __ arm920_setup
     . long     cpu_arch_name
     . long     cpu_elf_name
     . long     HWCAP_SWP  |  HWCAP_HALF  |  HWCAP_THUMB
     . long     cpu_arm920_name
     . long     arm920_processor_functions
     . long     v4wbi_tlb_fns
     . long     v4wb_user_fns
# ifndef  CONFIG_CPU_DCACHE_WRITETHROUGH
     . long     arm920_cache_fns
# else
     . long     v4wt_cache_fns
# endif
     . size     __ arm920_proc_info ,   .   -   __ arm920_proc_info


arch / arm / kernel / head - common . S
     . type     __ switch_data ,   % object
__ switch_data :
     . long      __ mmap_switched
     . long      __ data_loc            @ r4
     . long      __ data_start            @ r5
     . long      __ bss_start            @ r6
     . long     _end                @ r7
     . long     processor_id            @ r4
     . long      __ machine_arch_type        @ r5
     . long      __ atags_pointer            @ r6
     . long     cr_alignment            @ r7
     . long     init_thread_union  +  THREAD_START_SP @ sp

. . .
     . type     __ mmap_switched ,   % function
__ mmap_switched :
    adr    r3 ,   __ switch_data  +  4

    ldmia      { r4 ,  r5 ,  r6 ,  r7 }
    cmp    r4 ,  r5                @  Copy  data segment  if  needed
1 :     cmpne    r5 ,  r6
    ldrne    fp ,   [ r4 ] ,   # 4
    strne    fp ,   [ r5 ] ,   # 4
    bne    1b

    mov    fp ,   # 0                @ Clear BSS  ( and  zero fp )
1 :     cmp    r6 ,  r7
    strcc    fp ,   [ r6 ] , # 4
    bcc    1b

    ldmia    r3 ,   { r4 ,  r5 ,  r6 ,  r7 ,  sp }
    str    r9 ,   [ r4 ]             @ Save processor ID
    str    r1 ,   [ r5 ]             @ Save machine type
    str    r2 ,   [ r6 ]             @ Save atags pointer //将blob传递进来的tags物理地址数值存入__atags_pointer指针中
    bic    r4 ,  r0 ,   # CR_A        @ Clear  'A'  bit
    stmia    r7 ,   { r0 ,  r4 }     @ Save control  register  values
    b    start_kernel  //执行c函数


start_kernel
= > setup_arch ( & command_line ) //读出blob传进来的tags字符串参数,如果blob没有指定cmdline,那么使用make menuconfig指定的cmdline.
/*
setup_arch中首先对blob传递进来的tags们执行parse_tags解析,可能blob也传递cmdline命令行tag,所以这样blob传递的cmdline将去掉
make menuconfig内核自定义的cmdline.
arch/arm/kernel/setup.c|633| __tagtable(ATAG_CORE, parse_tag_core);
arch/arm/kernel/setup.c|649| __tagtable(ATAG_MEM, parse_tag_mem32);
arch/arm/kernel/setup.c|675| __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
arch/arm/kernel/setup.c|688| __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
arch/arm/kernel/setup.c|699| __tagtable(ATAG_INITRD, parse_tag_initrd);
arch/arm/kernel/setup.c|708| __tagtable(ATAG_INITRD2, parse_tag_initrd2);
arch/arm/kernel/setup.c|717| __tagtable(ATAG_SERIAL, parse_tag_serialnr);
arch/arm/kernel/setup.c|725| __tagtable(ATAG_REVISION, parse_tag_revision);
arch/arm/kernel/setup.c|733| __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
arch/arm/kernel/setup.c|751| __tagtable(ATAG_POWERUP_REASON, parse_tag_powerup_reason);
然后对cmdline命令行参数执行parse_cmdline
arch/arm/kernel/setup.c|458| __early_param("initrd=", early_initrd);
arch/arm/kernel/setup.c|503| __early_param("mem=", early_mem);
arch/arm/mm/mmu.c|124| __early_param("cachepolicy=", early_cachepolicy);
arch/arm/mm/mmu.c|132| __early_param("nocache", early_nocache);
arch/arm/mm/mmu.c|140| __early_param("nowb", early_nowrite);
arch/arm/mm/mmu.c|152| __early_param("ecc=", early_ecc);
*/

= > setup_command_line //设置cmdline
= > parse_early_param ( ) //提前执行如下方法
/*
drivers/pci/pci.c|1667| early_param("pci", pci_setup);
init/main.c|154| early_param("nosmp", nosmp);
init/main.c|165| early_param("maxcpus", maxcpus);
init/main.c|245| early_param("debug", debug_kernel);
init/main.c|246| early_param("quiet", quiet_kernel);
init/main.c|254| early_param("loglevel", loglevel);
kernel/printk.c|488| early_param("ignore_loglevel", ignore_loglevel_setup);
mm/page_alloc.c|1976| early_param("numa_zonelist_order", setup_numa_zonelist_order);
mm/page_alloc.c|3941| early_param("kernelcore", cmdline_parse_kernelcore);
mm/page_alloc.c|3942| early_param("movablecore", cmdline_parse_movablecore);
*/

= > parse_args ( "Booting kernel" ,  static_command_line ,   __ start __ _param ,
          __ stop __ _param  -   __ start __ _param ,
          & unknown_bootoption ) ; //所以__stop___param - __start___param等于0
/*
因为上面已经尝试执行early_param()等了,
现在尝试执行__setup()的命令.
arch/arm/kernel/process.c|82| __setup("nohlt", nohlt_setup);
arch/arm/kernel/process.c|83| __setup("hlt", hlt_setup);
arch/arm/kernel/process.c|186| __setup("reboot=", reboot_setup);
arch/arm/mach-pxa/pxa3xx.c|61| __setup("android", android_setup);
arch/arm/mach-pxa/pxa3xx.c|75| __setup("i2c_fastmode", i2c_fastmode_setup);
arch/arm/mach-pxa/pxa930.c|40| __setup("comm_v75", comm_v75_setup);
drivers/block/brd.c|407| __setup("ramdisk=", ramdisk_size);
drivers/block/brd.c|408| __setup("ramdisk_size=", ramdisk_size2);
drivers/video/fbmem.c|1654| __setup("video=", video_setup);
drivers/video/console/fbcon.c|548| __setup("fbcon=", fb_console_setup);
drivers/net/netconsole.c|64| __setup("netconsole=", option_setup);
drivers/serial/pxa.c|123| __setup("uart_dma", uart_dma_setup);
fs/nfs/nfsroot.c|400| __setup("nfsroot=", nfs_root_setup);
init/do_mounts.c|36| __setup("load_ramdisk=", load_ramdisk);
init/do_mounts.c|54| __setup("ro", readonly);
init/do_mounts.c|55| __setup("rw", readwrite);
init/do_mounts.c|125| __setup("root=", root_dev_setup);
init/do_mounts.c|135| __setup("rootwait", rootwait_setup);
init/do_mounts.c|158| __setup("rootflags=", root_data_setup);
init/do_mounts.c|159| __setup("rootfstype=", fs_names_setup);
init/do_mounts.c|160| __setup("rootdelay=", root_delay_setup);
init/main.c|188| __setup("reset_devices", set_reset_devices);
init/main.c|336| __setup("init=", init_setup);
init/main.c|348| __setup("rdinit=", rdinit_setup);
init/main.c|660| __setup("initcall_debug", initcall_debug_setup);
init/main.c|761| __setup("nosoftlockup", nosoftlockup_setup);
kernel/printk.c|185| __setup("log_buf_len=", log_buf_len_setup);
kernel/printk.c|199| __setup("console_loglevel=", console_loglevel_setup);
kernel/printk.c|224| __setup("boot_delay=", boot_delay_setup);
kernel/printk.c|881| __setup("console=", console_setup);
kernel/printk.c|949| __setup("no_console_suspend", console_suspend_disable);
net/ethernet/eth.c|63| __setup("ether=", netdev_boot_setup);
net/core/dev.c|551| __setup("netdev=", netdev_boot_setup);
net/ipv4/ipconfig.c|1541| __setup("ip=", ip_auto_config_setup);
net/ipv4/ipconfig.c|1542| __setup("nfsaddrs=", nfsaddrs_config_setup);
net/ipv4/ipconfig.c|1543| __setup("dhcpclass=", vendor_class_identifier_setup);
net/ipv4/tcp.c|2611| __setup("thash_entries=", set_thash_entries);
net/ipv4/route.c|2991| __setup("rhash_entries=", set_rhash_entries);
*/

= = = = = = = = = = = = = = = = = = = = = = = = = =
void   __ init setup_arch ( char   * * cmdline_p )
{
     struct  tag  * tags  =   ( struct  tag  * ) & init_tags ;
     char   * from  =  default_command_line ; //从default_command_line读取cmdline命令行参数
     . . .
     if   ( __ atags_pointer ) //__atags_pointer为blob传进来的参数,优先考虑,对于我的就是上面blob定义的:
//#define BOOT_PARAMS (0x80000100)//blob传递给kernel的tags物理存储地址,kenel会调用
        tags  =  phys_to_virt ( __ atags_pointer ) ;
     else   if   ( mdesc - > boot_params ) //如果blob没有传递参数进来,那么查看默认的地址处,是否有合法的tags
        tags  =  phys_to_virt ( mdesc - > boot_params ) ;
     . . .
     if   ( tags - > hdr . tag  ! =  ATAG_CORE )
        convert_to_tag_list ( tags ) ;
     if   ( tags - > hdr . tag  ! =  ATAG_CORE )
        tags  =   ( struct  tag  * ) & init_tags ; //如果没有有效的tags,那么使用默认的init_tags
     if   ( tags - > hdr . tag  = =  ATAG_CORE )   {
         if   ( meminfo . nr_banks  ! =  0 )
            squash_mem_tags ( tags ) ;
        save_atags ( tags ) ;
        parse_tags ( tags ) ; //ok,调用tags解析处理函数
     }
     . . .
     memcpy ( boot_command_line ,  from ,  COMMAND_LINE_SIZE ) ; //将default_command_line中的内容拷贝到boot_command_line中,
//因为之前经过了parse_tags(tags);操作,所以这时default_command_line中的内容可能是1.CONFIG_CMDLINE或者2.blob传递进来的cmdline.
    boot_command_line [ COMMAND_LINE_SIZE - 1 ]   =   '\0' ;
    parse_cmdline ( cmdline_p ,  from ) ;
//尝试解析cmdline中的early_params部分,这些设置需要提前被解析出来,比如"mem=",因为紧接着就要buddy内存.
//比如:"initrd=","mem=","cachepolicy=","nocache","nowb","ecc="等cmdline命令行.
    paging_init ( & meminfo ,  mdesc ) ;
     . . .
}

mdesc - > boot_params位于
arch / arm / mach - pxa / luther . c
MACHINE_START ( LUTHER ,   "luther" )
     . phys_io  =  0x40000000 ,
     . boot_params  =  0xa0000100 ,
     . io_pg_offst  =   ( io_p2v ( 0x40000000 )   > >  18 )   &  0xfffc ,
     . map_io  =  pxa_map_io ,
     . init_irq  =  pxa3xx_init_irq ,
     . timer  =   & pxa_timer ,
     . init_machine  =  luther_init ,
MACHINE_END

= > setup_arch
= = > parse_tags
= = > parse_tag
static   void   __ init parse_tags ( const   struct  tag  * t )
{
     for   ( ;  t - > hdr . size ;  t  =  tag_next ( t ) )
         if   ( ! parse_tag ( t ) )
    
            printk ( KERN_WARNING
                 "Ignoring unrecognised tag 0x%08x\n" ,
                t - > hdr . tag ) ;
}
static   int   __ init parse_tag ( const   struct  tag  * tag )
{
     extern   struct  tagtable  __ tagtable_begin ,   __ tagtable_end ;
     struct  tagtable  * t ;

     for   ( =   & __ tagtable_begin ;  t  <   & __ tagtable_end ;  t + + )
         if   ( tag - > hdr . tag  = =  t - > tag )   {
            t - > parse ( tag ) ;
             break ;
         }

     return  t  <   & __ tagtable_end ;
}
# define   __ tag  __ used  __ attribute __ ( ( __ section __ ( ".taglist.init" ) ) )
# define   __ tagtable ( tag ,  fn )  \
static   struct  tagtable  __ tagtable_ # # fn  __ tag  =   {  tag ,  fn  }
arch / arm / kernel / vmlinux . lds
   __ tagtable_begin  =   . ;
    * ( . taglist . init )
   __ tagtable_end  =   . ;
arch / arm / kernel / setup . c
# ifdef  CONFIG_CMDLINE_BOOL
static   char  default_command_line [ COMMAND_LINE_SIZE ]   __ initdata  =  CONFIG_CMDLINE ;
# endif
这里default_command_line的CONFIG_CMDLINE由make menuconfig生成 , 最后保存在include / linux / autoconf . h文件中 [ luther . gliethttp ] .
static   int   __ init parse_tag_cmdline ( const   struct  tag  * tag )
{
    strlcpy ( default_command_line ,  tag - > u . cmdline . cmdline ,  COMMAND_LINE_SIZE ) ;
     return  0 ;
}
# define  ATAG_CMDLINE    0x54410009 //如果blob传递了cmdline对应的tag进入kernel,那么覆盖CONFIG_CMDLINE编译时定义的参数字符串.
__ tagtable ( ATAG_CMDLINE ,  parse_tag_cmdline ) ;

arch / arm / kernel / setup . c | 633 |   __ tagtable ( ATAG_CORE ,  parse_tag_core ) ;
arch / arm / kernel / setup . c | 649 |   __ tagtable ( ATAG_MEM ,  parse_tag_mem32 ) ;
arch / arm / kernel / setup . c | 675 |   __ tagtable ( ATAG_VIDEOTEXT ,  parse_tag_videotext ) ;
arch / arm / kernel / setup . c | 688 |   __ tagtable ( ATAG_RAMDISK ,  parse_tag_ramdisk ) ;
arch / arm / kernel / setup . c | 699 |   __ tagtable ( ATAG_INITRD ,  parse_tag_initrd ) ;
arch / arm / kernel / setup . c | 708 |   __ tagtable ( ATAG_INITRD2 ,  parse_tag_initrd2 ) ;
arch / arm / kernel / setup . c | 717 |   __ tagtable ( ATAG_SERIAL ,  parse_tag_serialnr ) ;
arch / arm / kernel / setup . c | 725 |   __ tagtable ( ATAG_REVISION ,  parse_tag_revision ) ;
arch / arm / kernel / setup . c | 733 |   __ tagtable ( ATAG_CMDLINE ,  parse_tag_cmdline ) ;
arch / arm / kernel / setup . c | 751 |   __ tagtable ( ATAG_POWERUP_REASON ,  parse_tag_powerup_reason ) ;

static   void   __ init parse_cmdline ( char   * * cmdline_p ,   char   * from )
{
     char  c  =   ' ' ,   * to  =  command_line ;
     int  len  =  0 ;

     for   ( ; ; )   {
         if   ( = =   ' ' )   {
             extern   struct  early_params __early_begin ,  __early_end ;
             struct  early_params  * p ;

             for   ( =   & __early_begin ;  p  <   & __early_end ;  p + + )   {
                 int  len  =   strlen ( p - > arg ) ;

                 if   ( memcmp ( from ,  p - > arg ,  len )   = =  0 )   {
                     if   ( to  ! =  command_line )
                        to  - =  1 ;
                    from  + =  len ;
                    p - > fn ( & from ) ;

                     while   ( * from  ! =   ' '   & &   * from  ! =   '\0' )
                        from + + ;
                     break ;
                 }
             }
         }
        c  =   * from + + ;
         if   ( ! c )
             break ;
         if   ( COMMAND_LINE_SIZE  < =   + + len )
             break ;
         * to + +   =  c ;
     }
     * to  =   '\0' ;
     * cmdline_p  =  command_line ;
}

arch / arm / kernel / vmlinux . lds
  __early_begin  =   . ;
    * ( . early_param . init )
  __early_end  =   . ;
# define   __early_param ( name , fn )                     \
static   struct  early_params __early_ # # fn  __ used            \
__ attribute __ ( ( __ section __ ( ".early_param.init" ) ) )   =   {  name ,  fn  }
arch / arm / kernel / setup . c | 458 |   __early_param ( "initrd=" ,  early_initrd ) ;
arch / arm / kernel / setup . c | 503 |   __early_param ( "mem=" ,  early_mem ) ;
arch / arm / mm / mmu . c | 124 |   __early_param ( "cachepolicy=" ,  early_cachepolicy ) ;
arch / arm / mm / mmu . c | 132 |   __early_param ( "nocache" ,  early_nocache ) ;
arch / arm / mm / mmu . c | 140 |   __early_param ( "nowb" ,  early_nowrite ) ;
arch / arm / mm / mmu . c | 152 |   __early_param ( "ecc=" ,  early_ecc ) ;
= = = = = = = = = = = = = = = = = = = = = = = = = =
static   void   __ init setup_command_line ( char   * command_line )
{
    saved_command_line  =  alloc_bootmem ( strlen   ( boot_command_line ) + 1 ) ; //申请内存
    static_command_line  =  alloc_bootmem ( strlen   ( command_line ) + 1 ) ;
     strcpy   ( saved_command_line ,  boot_command_line ) ;
     strcpy   ( static_command_line ,  command_line ) ;
//拷贝命令行参数字符串,因为setup_arch中,已经将default_command_line拷贝到了boot_command_line,
//所以该操作之后,saved_command_line和static_command_line中的cmdline字符串就是default_command_line中的字符串了,
//而default_command_line在setup_arch中经过了parse_tags(tags);操作,
//所以default_command_line中的内容可能是1.CONFIG_CMDLINE或者2.blob传递进来的cmdline.
}
= = = = = = = = = = = = = = = = = = = = = = = = = =
static   int  parse_one ( char   * param ,
          char   * val ,
          struct  kernel_param  * params ,  
          unsigned  num_params ,
          int   ( * handle_unknown ) ( char   * param ,   char   * val ) )
{
     unsigned   int  i ;

     /* Find parameter */
     for   ( =  0 ;  i  <  num_params ;  i + + )   { //没有调用
         if   ( parameq ( param ,  params [ i ] . name ) )   {
            DEBUGP ( "They are equal! Calling %p\n" ,
             params [ i ] . set ) ;
             return  params [ i ] . set ( val ,   & params [ i ] ) ;
         }
     }

     if   ( handle_unknown )   { //调用该方法处理该param,如:do_early_param
        DEBUGP ( "Unknown argument: calling %p\n" ,  handle_unknown ) ;
         return  handle_unknown ( param ,  val ) ;
     }

    DEBUGP ( "Unknown argument `%s'\n" ,  param ) ;
     return   - ENOENT ;
}
int  parse_args ( const   char   * name ,
      char   * args ,
      struct  kernel_param  * params ,
      unsigned  num ,
      int   ( * unknown ) ( char   * param ,   char   * val ) )
{
     char   * param ,   * val ;

    DEBUGP ( "Parsing ARGS: %s\n" ,  args ) ;

你可能感兴趣的:(系统启动)