0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

U-boot傳遞RAM和Linux kernel讀取RAM參數(shù)的解析

Q4MP_gh_c472c21 ? 2018-02-06 08:24 ? 次閱讀

U-boot會給Linux Kernel傳遞很多參數(shù),如:串口,RAM,videofb等。而Linux kernel也會讀取和處理這些參數(shù)。兩者之間通過struct tag來傳遞參數(shù)。U-boot把要傳遞給kernel的東西保存在struct tag數(shù)據(jù)結(jié)構(gòu)中,啟動kernel時,把這個結(jié)構(gòu)體的物理地址傳給kernel;Linux kernel通過這個地址,用parse_tags分析出傳遞過來的參數(shù)。

這里主要以U-boot傳遞RAM和Linux kernel讀取RAM參數(shù)為例進行說明。

1、u-boot給kernel傳RAM參數(shù)

./common/cmd_bootm.c文件中(指Uboot的根目錄),bootm命令對應(yīng)的do_bootm函數(shù),當(dāng)分析uImage中信息發(fā)現(xiàn)OS是Linux時,調(diào)用./lib_arm/bootm.c文件中的do_bootm_linux函數(shù)來啟動Linux kernel。

在do_bootm_linux函數(shù)中:

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

ulong addr, ulong *len_ptr, int verify)

{

......

#if defined (CONFIG_SETUP_MEMORY_TAGS) || \

defined (CONFIG_CMDLINE_TAG) || \

defined (CONFIG_INITRD_TAG) || \

defined (CONFIG_SERIAL_TAG) || \

defined (CONFIG_REVISION_TAG) || \

defined (CONFIG_LCD) || \

defined (CONFIG_VFD)

setup_start_tag (bd); //初始化tag結(jié)構(gòu)體開始

#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); //設(shè)置RAM參數(shù)

#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); //初始化tag結(jié)構(gòu)體結(jié)束

#endif

......

......

theKernel (0, machid, bd->bi_boot_params);

//傳給Kernel的參數(shù)= (struct tag *)型的bd->bi_boot_params

//bd->bi_boot_params在board_init函數(shù)中初始化,如對于at91rm9200,初始化在at91rm9200dk.c的board_init中進行:bd->bi_boot_params=PHYS_SDRAM + 0x100;

//這個地址也是所有taglist的首地址,見下面的setup_start_tag函數(shù)

}

對于setup_start_tag和setup_memory_tags函數(shù)說明如下。

函數(shù)setup_start_tag也在此文件中定義,如下:

static void setup_start_tag (bd_t *bd)

{

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

//初始化(struct tag *)型的全局變量params為bd->bi_boot_params的地址,之后的setup tags相關(guān)函數(shù)如下面的setup_memory_tags就把其它tag的數(shù)據(jù)放在此地址的偏移地址上。

params->hdr.tag = ATAG_CORE;

params->hdr.size = tag_size (tag_core);

params->u.core.flags = 0;

params->u.core.pagesize = 0;

params->u.core.rootdev = 0;

params = tag_next (params);

}

RAM相關(guān)參數(shù)在bootm.c中的函數(shù)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;

params->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);

} //初始化內(nèi)存相關(guān)tag

}

2、Kernel讀取U-boot傳遞的相關(guān)參數(shù)

對于Linux Kernel,ARM平臺啟動時,先執(zhí)行arch/arm/kernel/head.S,此文件會調(diào)用arch/arm/kernel/head-common.S和arch/arm/mm/proc-arm920.S中的函數(shù),并最后調(diào)用start_kernel:

......

b start_kernel

......

init/main.c中的start_kernel函數(shù)中會調(diào)用setup_arch函數(shù)來處理各種平臺相關(guān)的動作,包括了u-boot傳遞過來參數(shù)的分析和保存:

start_kernel()

{

......

setup_arch(&command_line);

......

}

其中,setup_arch函數(shù)在arch/arm/kernel/setup.c文件中實現(xiàn),如下:

void __init setup_arch(char **cmdline_p)

{

struct tag *tags = (struct tag *)&init_tags;

struct machine_desc *mdesc;

char *from = default_command_line;

setup_processor();

mdesc = setup_machine(machine_arch_type);

machine_name = mdesc->name;

if (mdesc->soft_reboot)

reboot_setup("s");

if(__atags_pointer)

//指向各種tag起始位置的指針,定義如下:

//unsigned int __atags_pointer __initdata;

//此指針指向__initdata段,各種tag的信息保存在這個段中。

tags = phys_to_virt(__atags_pointer);

else if (mdesc->boot_params)

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;

if (mdesc->fixup)

mdesc->fixup(mdesc, tags, &from, &meminfo);

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

if (meminfo.nr_banks != 0)

squash_mem_tags(tags);

save_atags(tags);

parse_tags(tags);

//處理各種tags,其中包括了RAM參數(shù)的處理。

//這個函數(shù)處理如下tags:

__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 = (unsigned long) &_text;

init_mm.end_code = (unsigned long) &_etext;

init_mm.end_data = (unsigned long) &_edata;

init_mm.brk = (unsigned long) &_end;

memcpy(boot_command_line, from, COMMAND_LINE_SIZE);

boot_command_line[COMMAND_LINE_SIZE-1] = '\0';

parse_cmdline(cmdline_p, from);//處理編譯內(nèi)核時指定的cmdline或u-boot傳遞的cmdline

paging_init(&meminfo, mdesc);

request_standard_resources(&meminfo, mdesc);

#ifdef CONFIG_SMP

smp_init_cpus();

#endif

cpu_init();

init_arch_irq = mdesc->init_irq;

system_timer = mdesc->timer;

init_machine = mdesc->init_machine;

#ifdef CONFIG_VT

#if defined(CONFIG_VGA_CONSOLE)

conswitchp = &vga_con;

#elif defined(CONFIG_DUMMY_CONSOLE)

conswitchp = &dummy_con;

#endif

#endif

early_trap_init();

}

對于處理RAM的tag,調(diào)用了parse_tag_mem32函數(shù):

static int __init parse_tag_mem32(const struct tag *tag)

{

......

arm_add_memory(tag->u.mem.start, tag->u.mem.size);

......

}

__tagtable(ATAG_MEM, parse_tag_mem32);

上述的arm_add_memory函數(shù)定義如下:

static void __init arm_add_memory(unsigned long start, unsigned long size)

{

struct membank *bank;

size -= start & ~PAGE_MASK;

bank = &meminfo.bank[meminfo.nr_banks++];

bank->start = PAGE_ALIGN(start);

bank->size = size & PAGE_MASK;

bank->node = PHYS_TO_NID(start);

}

如上可見,parse_tag_mem32函數(shù)調(diào)用arm_add_memory函數(shù)把RAM的start和size等參數(shù)保存到了meminfo結(jié)構(gòu)的meminfo結(jié)構(gòu)體中。最后,在setup_arch中執(zhí)行下面語句:

paging_init(&meminfo, mdesc);

對沒有MMU的平臺上調(diào)用arch/arm/mm/nommu.c中的paging_init,否則調(diào)用arch/arm/mm/mmu.c中的paging_init函數(shù)。這里暫不分析mmu.c中的paging_init函數(shù)。

3、關(guān)于U-boot中的bd和gd

U-boot中有一個用來保存很多有用信息的全局結(jié)構(gòu)體--gd_t(global data縮寫),其中包括了bd變量,可以說gd_t結(jié)構(gòu)體包括了u-boot中所有重要全局變量。最后傳遞給內(nèi)核的參數(shù),都是從gd和bd中來的,如上述的setup_memory_tags函數(shù)的作用就是用bd中的值來初始化RAM相應(yīng)的tag。

對于ARM平臺這個結(jié)構(gòu)體的定義大致如下:

include/asm-arm/global_data.h

typedef struct global_data {

bd_t *bd;

unsigned long flags;

unsigned long baudrate;

unsigned long have_console; /* serial_init() was called */

unsigned long reloc_off; /* Relocation Offset */

unsigned long env_addr; /* Address of Environment struct */

unsigned long env_valid; /* Checksum of Environment valid? */

unsigned long fb_base; /* base address of frame buffer */

void **jt; /* jump table */

} gd_t;

在U-boot中使用gd結(jié)構(gòu)之前要用先用宏DECLARE_GLOBAL_DATA_PTR來聲明。這個宏的定義如下:

include/asm-arm/global_data.h

#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")

從這個宏的定義可以看出,gd是一個保存在ARM的r8寄存器中的gd_t結(jié)構(gòu)體的指針。

本文的版本為U-boot-1.3.4、Linux-2.6.28,平臺是ARM。

U-boot傳遞RAM和Linux kernel讀取RAM參數(shù)的解析

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • RAM
    RAM
    +關(guān)注

    關(guān)注

    8

    文章

    1350

    瀏覽量

    114370
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11161

    瀏覽量

    208461
  • u-boot
    +關(guān)注

    關(guān)注

    0

    文章

    120

    瀏覽量

    38163
  • Kernel
    +關(guān)注

    關(guān)注

    0

    文章

    48

    瀏覽量

    11108

原文標(biāo)題:Uboot與Linux之間的參數(shù)傳遞詳解

文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    U-Boot介紹

    在移植 Linux之前我們需要先移植一個 bootloader 代碼,這個 bootloader 代碼用于啟動 Linux 內(nèi)核, bootloader有很多,常用的就是 U-Boot。
    的頭像 發(fā)表于 10-08 10:50 ?3802次閱讀

    U-boot的基本介紹

    從本文開始,將陸續(xù)推送“手把手教你移植U-boot”系列文章,目標(biāo)是由淺入深地講解U-boot的工作流程、原理、配置方法和移植方法,手把手教你完成U-boot的移植工作,默認(rèn)硬件開發(fā)平臺為ARM,操作系統(tǒng)為
    發(fā)表于 07-14 16:52 ?2649次閱讀
    <b class='flag-5'>U-boot</b>的基本介紹

    u-bootlinux kernel在RK3399上是如何部署的

    mainline 的 u-bootlinux kernel可能很多玩 Linux 的同學(xué)都聽過 mainline 或者 upstream 這兩個詞,但是又搞不清他們到底指的是什么
    發(fā)表于 05-07 12:04

    u-boot的Makefile分析

    u-boot的Makefile分析 U-BOOT是一個LINUX下的工程,在編譯之前必須已經(jīng)安裝對應(yīng)體系結(jié)構(gòu)的交叉編譯環(huán)境,這里只針對ARM,編譯器系列軟件為arm-linux-*。
    發(fā)表于 05-17 09:16 ?2040次閱讀

    u-boot簡介

    演化而來。其源碼目錄、編譯形式與Linux內(nèi)核很相似,事實上,不少U-Boot源碼就是根據(jù)相應(yīng)的Linux內(nèi)核源程序進行簡化而形成的,尤其是一些設(shè)備的驅(qū)動程序,這從U-Boot源碼的注
    發(fā)表于 10-14 11:17 ?3518次閱讀

    DENX U-BootLinux 使用手冊

    DENX U-BootLinux 使用手冊
    發(fā)表于 10-30 09:59 ?5次下載
    DENX <b class='flag-5'>U-Boot</b>及<b class='flag-5'>Linux</b> 使用手冊

    詳解U-Boot引導(dǎo)內(nèi)核分析

    bootm命令是用來引導(dǎo)經(jīng)過U-Boot的工具mkimage打包后的kernel image的。U-Boot源代碼的tools/目錄下有mkimage工具,這個工具可以用來制作不壓縮或者壓縮的多種可啟動映象文件。
    的頭像 發(fā)表于 04-13 15:22 ?5190次閱讀
    詳解<b class='flag-5'>U-Boot</b>引導(dǎo)內(nèi)核分析

    你了解u-bootlinux內(nèi)核間的參數(shù)傳遞過程?

    U-boot會給Linux Kernel傳遞很多參數(shù),如:串口,RAM,videofb、MAC地
    發(fā)表于 05-13 10:00 ?1655次閱讀
    你了解<b class='flag-5'>u-boot</b>與<b class='flag-5'>linux</b>內(nèi)核間的<b class='flag-5'>參數(shù)</b><b class='flag-5'>傳遞</b>過程?

    Linux下獲取虛擬地址對應(yīng)的物理地址的方式

    U-boot會給Linux Kernel傳遞很多參數(shù),如:串口,RAM,videofb等。而
    發(fā)表于 05-15 15:59 ?4223次閱讀

    Linux:使用 QEMU 測試 U-BOOT的步驟

    Linux:使用 QEMU 測試 U-BOOT的步驟
    的頭像 發(fā)表于 06-23 09:42 ?3304次閱讀
    <b class='flag-5'>Linux</b>:使用 QEMU 測試 <b class='flag-5'>U-BOOT</b>的步驟

    設(shè)備樹的傳遞kernel 對設(shè)備樹的解析

    當(dāng) U-Boot 將設(shè)備樹加載到內(nèi)存指定位置后,ARM 內(nèi)核的 SoC 以通用寄存器 r2 來傳遞 dtb 在內(nèi)存中的地址。kernel 獲取到該地址后對 dtb 文件做進一步的處理。 設(shè)備樹的
    的頭像 發(fā)表于 07-29 11:19 ?2302次閱讀
    設(shè)備樹的<b class='flag-5'>傳遞</b>及<b class='flag-5'>kernel</b> 對設(shè)備樹的<b class='flag-5'>解析</b>

    深度解析U-Boot網(wǎng)絡(luò)實現(xiàn)

    對于U-Boot而言,并沒有完整的實現(xiàn)上述模型,u-boot需要控制固件的尺寸,所以根據(jù)需要做了一些簡化,其拓?fù)淇蚣苋缦聢D所示:
    發(fā)表于 02-07 11:53 ?2次下載
    深度<b class='flag-5'>解析</b><b class='flag-5'>U-Boot</b>網(wǎng)絡(luò)實現(xiàn)

    U-Boot架構(gòu)淺析

    導(dǎo)讀:嵌入式Linux系統(tǒng)搭建,bootloader是必不可少的一環(huán),而U-Boot已成嵌入式Linux事實標(biāo)準(zhǔn)。所以較為深入的分析U-Boot的設(shè)計,對于更...
    發(fā)表于 02-07 11:56 ?7次下載
    <b class='flag-5'>U-Boot</b>架構(gòu)淺析

    Linux U-Boot開發(fā)指南

    介紹 U-Boot 的編譯打包、基本配置、常用命令的使用、基本調(diào)試方法等, 為 U-BOOT 的移植及應(yīng)用開發(fā)提供了基礎(chǔ)。
    的頭像 發(fā)表于 03-06 10:28 ?1221次閱讀
    <b class='flag-5'>Linux</b> <b class='flag-5'>U-Boot</b>開發(fā)指南

    如何在U-BOOTboot.scr中加載bit文件

    在2020.1版本之后,u-boot階段會執(zhí)行boot.scr來加載后續(xù)的kernel和rootfs
    的頭像 發(fā)表于 07-12 15:43 ?2089次閱讀
    如何在<b class='flag-5'>U-BOOT</b>的<b class='flag-5'>boot</b>.scr中加載bit文件