Red de conocimiento informático - Material del sitio web - Cómo implementar el paso de parámetros entre uboot y Linux

Cómo implementar el paso de parámetros entre uboot y Linux

U-boot pasará una gran cantidad de parámetros al kernel de Linux, como puerto serie, RAM, videofb, etc. El kernel de Linux lee y procesa estos parámetros. Ambos pasan parámetros a través de etiquetas de estructura. U-boot guarda los parámetros que se pasarán al kernel en la estructura de datos de la etiqueta de estructura y pasa la dirección física de la estructura al kernel cuando se inicia el kernel. El kernel de Linux usa parse_tags para analizar los parámetros pasados ​​a través de esta dirección;

Este artículo toma principalmente como ejemplos U-boot que pasa RAM y parámetros de lectura del kernel de Linux.

1. U-boot pasa los parámetros de RAM al kernel

En el archivo /common/cmd_bootm.c (refiriéndose al directorio raíz de Uboot), el comando bootm corresponde a. la función do_bootm Al analizar Cuando la información en uImage encuentra que el sistema operativo es Linux, se llama.

En la función do_bootm_linux:

void do_bootm_linux (cmd_tbl_t *cmdtp, int. bandera, int argc, char *argv[] ,\

ulong addr, ulong *len_ptr, int verificar)

{

......

#si está definido (CONFIG_SETUP_MEMORY_TAGS) ||\

definido (CONFIG_CMDLINE_TAG) ||

definido (CONFIG_INITRD_TAG) ||\

definido(CONFIG_SERIAL_TAG) ||\

definido (CONFIG_REVISION_TAG) ||\

definido (CONFIG_LCD) ||

definido (CONFIG_VFD)

setup_start_tag (bd); //inicializar etiqueta struct start

#ifdef CONFIG_SERIAL_TAG

setup_serial_tag (¶ms);

#endif

#ifdef CONFIG_REVISION_TAG

setup_revision_tag (¶ms);

#endif

#ifdef CONFIG_SETUP_MEMORY_TAGS

setup_memory_ tags (bd); Establecer parámetros de RAM

#endif

#ifdef CONFIG_CMDLINE_TAG

setup_commandline_tag (bd, línea de comando);

#endif

# ifdef CONFIG_INITRD_TAG

if (initrd_start &&

# ifdefinido (CONFIG_VFD) ||definido (CONFIG_LCD)

setup_videolfb_tag ((gd_t *) gd) ;

#endif

setup_end_tag ​​​​(bd); //estructura de etiqueta final de inicialización

#endif

.

.....

......

theKernel (0, machid, bd->bi-boot_params

// pasado a); Parámetros del kernel = (etiqueta de estructura *) -tipo bd->bi-boot_params

// bd->bi-boot_params se usa en board_boot_structure. los parámetros se inicializan en la función board_init, por ejemplo, para at91rm9200, los parámetros se inicializan en la función board_init. Para at91rm9200, la inicialización se completa en board_init de at91rm9200dk.c: bd->bi-boot_params=PHYS_SDRAM + 0x100;

// Esta dirección también es la primera dirección de todas las listas de etiquetas; consulte setup_start_tag a continuación Funciones

}

Las funciones setup_start_tag y setup_memory_tags se describen a continuación.

La función setup_start_tag también se define en el archivo de la siguiente manera:

static void setup_start_tag (bd_t *bd)

{

params = (struct tag *) bd->bi_boot_ params;

// Inicializa los parámetros de la variable global del tipo (struct tag *) en la dirección de bd->bi_boot_params y luego configura los parámetros relacionados con la etiqueta. funciones (como las siguientes Los datos de setup_memory_tags) se colocan en la dirección de desplazamiento de esta dirección.

Parámetro->hdr.tag = ATAG_CORE;

Parámetro->hdr.size = tag_size (tag_core);

Parámetro->u.core.flags = 0;

Parámetros->u.core.gt;u.core.pagesize = 0;

params->u.core.rootdev = 0;

params = tag_next (params);

}

Los parámetros relacionados con la RAM se inicializan en bootm en la función setup_memory_tags:

static void setup_memory_tags (bd_t * bd )

{

int i;

for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {

params->hdr.tag = ATAG_MEM ;

Parámetro->hdr.size = tag_size (tag_mem32);

params->u.mem.start = bd->bi_dram[i].start;

params->u.mem.size = bd->bi_dram[i].size;

params = tag_next (params);

} // La inicialización está relacionada a la función de memoria.

//Inicializar marcadores relacionados con la memoria

}

2. El kernel lee los parámetros relevantes pasados ​​por U-boot

Para el kernel de Linux, cuando el ARM se inicia la plataforma, primero ejecuta arch/arm/kernel/head.S, llama a funciones en arch/arm/kernel/head-common.S y arch/arm/mm/proc-arm920, y finalmente llama a start_kernel:

......

b start_kernel

......

La función start_kernel en init/main.c llama a setup_arch función para procesar cada operación relacionada con la plataforma, incluido el análisis y el guardado de parámetros pasados ​​por u-boot:

start_kernel()

{

.... ..

setup_arch(&command_line);

......

}

La función setup_arch está en arch/arm /kernel/setup La función setup_arch en el archivo .c se implementa de la siguiente manera:

void __init setup_arch(char**cmdline_p)

{

etiqueta de estructura *tags = (struct tag * )&init_tags;

struct machine_desc *mdesc;

char *from = default_command_line;

setup_processor() ;

mdesc = setup_machine( machine_arch_type);

nombre_máquina = mdesc->nombre;

if (mdesc->soft_reboot)

reboot_ setup("s ");

if (__atags_pointer)

// Punteros a las posiciones iniciales de varias etiquetas, definidos de la siguiente manera:

///unsigned int __atags_pointer __initdata ;

/// Este puntero apunta al segmento __ initdata, que almacena diversa información de etiquetas.

etiquetas = phys_to_virt(__atags_pointer);

else if (mdesc->boot_params)

etiquetas = phys_to_virt(mdesc->boot_params

);

if (etiquetas->hdr.tag ! = ATAG_CORE)

convert_to_tag_list(etiquetas);

if (etiquetas->hdr.tag ! = ATAG_CORE)

convert_to_tag_list(etiquetas);

if (etiquetas->hdr.tag ! = ATAG_CORE)

if (etiquetas->hdr.tag !tag ! = ATAG_CORE)

etiquetas = (estructura etiqueta *)&init_tags;

if (mdesc->fixup)

mdesc->fixup(mdesc, etiquetas, &from, &. meminfo) ;

if (tags->hdr.tag == ATAG_CORE) {

if (meminfo.nr_banks !

// Esta función maneja las siguientes etiquetas:

__tagtable(ATAG_MEM, parse_tag_mem32);

__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);

__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);

__tagtable ( ATAG_SERIAL, parse_tag_serialnr);

__tagtable(ATAG_REVISION, parse_ tag_revision);

__tagtable(ATAG_CMDLINE, parse_tag_cmdline

}

); init_mm .start_code = (largo sin firmar) &_text;

init_mm.end_code = (largo sin firmar) &_etext;

init_mm.end_data = (largo sin firmar) &_edata;

init_mm.end_code = (largo sin firmar) &_etext;

init_mm.end_data = (largo sin firmar) &_edata;