uboot引導linux內核,u-boot啟動內核的幾種方式

1.uboot啟動內核的代碼縮減如下:

s = getenv ("bootcmd");

debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "");

if (bootdelay >= 0 && s && !abortboot (bootdelay))

{run_command (s, 0);

}

2.假設bootcmd = nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0

<1> nand read.jffs2 0x30007FC0 kernel

nand read.jffs2 0x30007FC0 kernel;

從nand讀出內核:從哪里讀??? 從kernel分區

放到哪里去?-0x30007FC0

下面講解什么是分區:

就是將nand劃分為幾個區域,一般如下:

bootloader-》params-》kernel-》root

這些分區的劃分是在/include/configs/mini2440.h中寫死的:

#define MTDPARTS_DEFAULT "mtdparts=nandflash0:250k@0(bootloader)," \

"128k(params)," \

"5m(kernel)," \

"-(root)"

注:@0表示從0地址開始,250k的bootloader分區可能對某些uboot不夠用,這里只是舉例而已。

將上面的信息換算成十六進制:

#????name???????????? 大小????????在nand上的起始地址

0????bootloader???? 0x00040000????????0x00000000

1????params????????0x00020000??????????????0x00040000

2????kernel????????0x00200000????????0x00060000

3????root????????0xfda00000????????0x00260000

那么上面的nand read.jffs2 0x30007FC0 kernel就等價于:

nand read.jffs2 0x30007FC0 0x00060000 0x00200000

注:這里的read.jffs2并不是指定要什么特定的格式,而是用read.jffs2不需要塊/頁對齊,所以這個kernel的分區大小可以

隨意定。

<2> bootm 0x30007FC0

關鍵函數do_bootm()

flash上存的內核:uImage

uImage = 頭部+真正的內核

頭部的定義如下:

typedef struct image_header {

uint32_t????ih_magic;????/* Image Header Magic Number????*/

uint32_t????ih_hcrc;????/* Image Header CRC Checksum????*/

uint32_t????ih_time;????/* Image Creation Timestamp????*/

uint32_t????ih_size;????/* Image Data Size????????*/

uint32_t????ih_load;????/* Data???? Load??Address????????*/

uint32_t????ih_ep;????????/* Entry Point Address????????*/

uint32_t????ih_dcrc;????/* Image Data CRC Checksum????*/

uint8_t????????ih_os;????????/* Operating System????????*/

uint8_t????????ih_arch;????/* CPU architecture????????*/

uint8_t????????ih_type;????/* Image Type????????????*/

uint8_t????????ih_comp;????/* Compression Type????????*/

uint8_t????????ih_name[IH_NMLEN];????/* Image Name????????*/

} image_header_t;

我們需要關心的是:

uint32_t????ih_load;????/* Data???? Load??Address????????*/

uint32_t????ih_ep;????????/* Entry Point Address????????*/

ih_load是加載地址,即內核運行是應該位于的地方

ih_ep是入口地址,即內核的入口地址

這與uboot是類似的,uboot的加載地址是TEXT_BASE = 0x33F80000;入口地址是start.S中的_start。

其實我們把內核中nand讀出來的時候是可以放在內核的任何地方的,如0x31000000,0x32000000等等,只要它不破壞uboot所占用的內存空間就可以了,如下圖:

從0x33F4DF74-0x30000000都是可以用的。

那么為什么既然設定好了加載地址和入口地址內核還能隨意放呢?

那是因為uImage有一個頭部!頭部里有加載地址和入口地址,當我們用bootm xxx的時候,

do_bootm這個函數會先去讀uImage的頭部以獲取該uImage的加載地址和入口地址,當發現該uImage目前所處的內存地址不等于它的加載地址時,該函數會將該uImage移動到它的加載地址上,在代碼中體現如下:

case IH_COMP_NONE::

if (load != image_start)

{

memmove_wd ((void *)load, (void *)image_start, image_len, CHUNKSZ);

}

另外,當我們的內核正好處于頭部指定的加載地址的話,那么就不用uboot的do_bootm函數來幫我們搬運內核了,這樣可以節省啟動時間。這就是為什么我們一般都下載uImage到

0x30007FC0的原因了!

我們所用的內核加載地址是0x30008000,而頭部的大小為64個字節,所以將內核拷貝到0x30007FC0時,再加載頭部的64個字節,內核正好位于0x30008000處!

現在總結bootm做了什么:

1.????讀取頭部

2.????將內核移動到加載地址

3.????啟動內核

具體如何啟動內核?

使用do_bootm_linux(),在/lib_arm/bootm.c定義,因為我們已經知道入口地址了,所以只需跳到入口地址就可以啟動linux內核了,但是在這之前需要做一件事————uboot傳遞參數給內核!!

現在來分析do_bootm_linux()這個函數:

theKernel = (void (*)(int, int, uint))images->ep;//先是將入口地址賦值給theKernel

theKernel (0, machid, bd->bi_boot_params);//然后是調用thekernel

函數,以0,machid,bd->bi_boot_params作為參數

下面分析這三個參數:

1.machid就是uboot里設置好的板子的機器碼,mini2440的是MACH_TYPE_MINI2440 (1999),內核所設置的機器碼和uboot所設置的機器碼必須一致才能啟動內核

2.bd->bi_boot_parmas就是uboot需傳遞給內核的啟動參數所位于的地址

3.0暫時還不知道什么作用/**********************************************/

那么uboot傳給內核的啟動參數是在哪里設置的呢?

其實就是在調用????theKernel (0, machid, bd->bi_boot_params);前面的一小段代碼里設置的,下面我截取了部分片段:

setup_start_tag (bd);

setup_revision_tag (&params);

setup_memory_tags (bd);

setup_commandline_tag (bd, commandline);

setup_initrd_tag (bd, images->rd_start, images->rd_end);

setup_videolfb_tag ((gd_t *) gd);

setup_end_tag (bd);

每一個啟動參數對應一個tag結構體,所謂的設置傳遞參數其實就是初始化這些tag的值,想了解這個結構體以及這些tag的值是如何設置的請看韋東山的書關于uboot移植章節!

下面我們看一下setup_start_tag(bd)這個函數先:

static void setup_start_tag (bd_t *bd)

{

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

//在board.c中有一句gd->bd->bi_boot_params = 0x30000100,這里設置了參數存放的位置

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

}

我們再來看下setup_commandline_tag (bd, commandline);這個函數:

static void setup_commandline_tag (bd_t *bd, char *commandline)

{

// commandline就是我們的bootargs

char *p;

if (!commandline)

return;

for (p = commandline; *p == ' '; p++);

if (*p == '\0')

return;

params->hdr.tag = ATAG_CMDLINE;

params->hdr.size =

(sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;

strcpy (params->u.cmdline.cmdline, p);

params = tag_next (params);

}

Linux內核啟動時就會去讀取這些tag參數

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/532807.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/532807.shtml
英文地址,請注明出處:http://en.pswp.cn/news/532807.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

跟我一起寫makefile: 概述、介紹、規則

跟我一起寫makefile 概述、介紹、規則 轉自&#xff1a;https://seisman.github.io/how-to-write-makefile/rules.html 概述 什么是makefile&#xff1f;或許很多Windows的程序員都不知道這個東西&#xff0c;因為那些Windows的集成開發環境&#xff08;integrated developm…

linux內核中cent文件夾,Centos 中如何快速定制二進制的內核 RPM 包

1、rpm 制作前的環境準備&#xff1a;yum install -y ncurses-devel qt-devel rpm-build redhat-rpm-config asciidoc hmaccalc perl-ExtUtils-Embed xmlto audit-libs-devel binutils-devel elfutils-devel elfutils-libelf-devel newt-devel python-devel zlib-devel bc2、準…

TabError- inconsistent use of tabs and spaces in indentation 查驗及解決方法

TabError: inconsistent use of tabs and spaces in indentation 查驗及解決方法 報錯代碼 def eccv16(pretrainedTrue):model ECCVGenerator()if(pretrained):import torch.utils.model_zoo as model_zoomodel.load_state_dict(torch.load(/home/ps/.cache/torch/hub/check…

linux用xshell編輯文件,Linux遠程管理器xshell和xftp使用教程

Xshell 是一個強大的安全終端模擬軟件&#xff0c;它支持SSH1, SSH2, 以及Microsoft Windows 平臺的TELNET 協議。Xftp 是一個基于 MS windows 平臺的功能強大的SFTP、FTP 文件傳輸軟件。安裝完畢后打開xshell設置網站帳號信息設置主機信息設置服務器帳號設置字符集編碼設置好了…

strict=False 但還是size mismatch for []: copying a param with shape [] from checkpoint,the shape in cur

strictFalse 但還是size mismatch for []: copying a param with shape [] from checkpoint,the shape in cur 問題 我們知道通過 model.load_state_dict(state_dict, strictFalse)可以暫且忽略掉模型和參數文件中不匹配的參數&#xff0c;先將正常匹配的參數從文件中載入模…

linux中權限765啥意思,Linux中的文件權限

Linux系統中的每一個文件都與多種權限類型相關聯。在這些權限中&#xff0c;我們主要和三類權限打交道&#xff1a;用戶(user)、用戶組(group)和其他用戶(others)。用戶是文件的所有者&#xff1b;用戶組是指和文件所有者在同一組的其他多個用戶的集合&#xff1b;其他用戶是除…

CV中的色彩空間大全

HSI、HSV、RGB、CMY、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV顏色模型 HSV顏色空間 HSV(hue,saturation,value)顏色空間的模型對應于圓柱坐標系中的一個圓錐形子集&#xff0c;圓錐的頂面對應于V1. 它包含RGB模型中的R1&#xff0c;G1&#xff0c;B1 三個面&#xff0c;所代表的…

linux 系統調用時怎么知道當前上下文屬于那個進程,linux – 編寫系統調用來計算進程的上下文切換...

如果您的系統調用只應報告統計信息,則可以使用內核中已有的上下文切換計數代碼.struct rusage {...long ru_nvcsw; /* voluntary context switches */long ru_nivcsw; /* involuntary context switches */};您可以通過運行來嘗試&#xff1a;$/usr/bin/time -v /bin/ls -R....V…

linux串口緩沖區的大小,linux-----------串口設置緩沖器的大小

轉自:http://stackoverflow.com/questions/10815811/linux-serial-port-reading-can-i-change-size-of-input-bufferYou want to use the serial IOCTL TIOCSSERIAL which allows changing both receive buffer depth and send buffer depth (among other things). The maximum…

FLOPs、FLOPS、Params的含義及PyTorch中的計算方法

FLOPs、FLOPS、Params的含義及PyTorch中的計算方法 含義解釋 FLOPS&#xff1a;注意全大寫&#xff0c;是floating point operations per second的縮寫&#xff08;這里的大S表示second秒&#xff09;&#xff0c;表示每秒浮點運算次數&#xff0c;理解為計算速度。是一個衡量…

設置中文linux輸入ubuntu,Linux_ubuntu怎么設置成中文?ubuntu中文設置圖文方法,  很多朋友安裝ubuntu后,發 - phpStudy...

ubuntu怎么設置成中文&#xff1f;ubuntu中文設置圖文方法很多朋友安裝ubuntu后&#xff0c;發現都是英文&#xff0c;看不懂要怎么辦?其實ubuntu是可以設置成中文的&#xff0c;下文小編就為大家帶來ubuntu中文的設置方法&#xff0c;一起去看下設置方法吧。ubuntu中文設置方…

科普 | 單精度、雙精度、多精度和混合精度計算的區別是什么?

科普 | 單精度、雙精度、多精度和混合精度計算的區別是什么? 轉自&#xff1a;https://zhuanlan.zhihu.com/p/93812784 我們提到圓周率 π 的時候&#xff0c;它有很多種表達方式&#xff0c;既可以用數學常數3.14159表示&#xff0c;也可以用一長串1和0的二進制長串表示。 …

linux 磁盤分配 簡書,linux 磁盤分區

1物理磁盤的構成&#xff1a; 盤面&#xff1a;由一圈一圈的磁道組成機械手臂&#xff1a;讀取數據主軸馬達&#xff1a;幫助機械手臂轉動2 扇區&#xff1a;磁盤上存取數據的最小單位512字節按照扇區分配大小&#xff0c;如果數據只有一字節也會占用512字節簇&#xff1a;用若…

條件控制與條件傳送詳解

條件控制與條件傳送詳解 提要 CSAPP3e中文譯本 3.6.5 用條件控制來實現條件分支 3.6.6 用條件傳送來實現條件分支 CSAPP3e第三章前面主要是介紹了機器級代碼的二進制形式和匯編形式、反匯編、x86匯編的基礎指令、條件碼及其訪問方式等。 在介紹到匯編語言的條件分支時分了兩…

聯合體(union)的使用方法及其本質

聯合體&#xff08;union&#xff09;的使用方法及其本質 轉自&#xff1a;https://blog.csdn.net/huqinwei987/article/details/23597091 有些基礎知識快淡忘了&#xff0c;所以有必要復習一遍&#xff0c;在不借助課本死知識的前提下做些推理判斷&#xff0c;溫故知新。 1…

linux設備驅動之串口移植,Linux設備驅動之UART驅動結構

一、對于串口驅動Linux系統中UART驅動屬于終端設備驅動&#xff0c;應該說是實現串口驅動和終端驅動來實現串口終端設備的驅動。要了解串口終端的驅動在Linux系統的結構就先要了解終端設備驅動在Linux系統中的結構體系&#xff0c;一方面自己了解的不夠&#xff0c;另一發面關于…

linux python復制安裝,復制一個Python全部環境到另一個環境,python另一個,導出此環境下安裝的包...

復制一個Python全部環境到另一個環境&#xff0c;python另一個,導出此環境下安裝的包導出此環境下安裝的包的版本信息清單pipfreeze>requirements.txt聯網&#xff0c;下載清單中的包到all-packet文件夾[[email protected] ~]# pip download -d ./all-packet -r requirement…

NVIDIA英偉達的Multi-GPU多卡通信框架NCCL

NVIDIA英偉達的Multi-GPU多卡通信框架NCCL 筆者注&#xff1a;NCCL 開源項目地址&#xff1a;https://github.com/NVIDIA/nccl 轉自&#xff1a;https://www.zhihu.com/question/63219175/answer/206697974 NCCL是Nvidia Collective multi-GPU Communication Library的簡稱&…

C語言n個坐標點間的最大距離,c語言已知兩點坐標,求另一點到穿過這兩點的直線最短距離。...

c語言已知兩點坐標&#xff0c;求另一點到穿過這兩點的直線最短距離。以下文字資料是由(歷史新知網www.lishixinzhi.com)小編為大家搜集整理后發布的內容&#xff0c;讓我們趕快一起來看一下吧&#xff01;c語言已知兩點坐標&#xff0c;求另一點到穿過這兩點的直線最短距離。#…

[分布式訓練] 單機多卡的正確打開方式:理論基礎

[分布式訓練] 單機多卡的正確打開方式&#xff1a;理論基礎 轉自&#xff1a;https://fyubang.com/2019/07/08/distributed-training/ 瓦礫由于最近bert-large用的比較多&#xff0c;踩了很多分布式訓練的坑&#xff0c;加上在TensorFlow和PyTorch之間更換&#xff0c;算是熟…