轉: Embedded.Linux.Primer.A.Practical.Real.World.Approach.Sep.2006.chm
Bootloader與Bootstrap再定義上有什饃差異呢?以下內容則是由網路上蒐集而來,,客觀的了解一下吧!有錯誤請糾正,非常感謝!
一般早期SOC 都會有 三個階段loader.(早期的說法)
- S1-loader : Bootstrap 是內建在 SOC 裡, 把S2 Loader Download 到 RAM中.
- S2-loader : 透過Bootstrap download到RAM的程式,一般這個code都會含燒寫 flash,及RS-232.
- S3-loader : 透過S2-loader Download到RAM並燒錄到flash或EEROM的程式, 也就是一般OS的loader, 也稱為Bootloader.
基本上S3-loader完成後, 以後就不用S1-loader & S2-loader, 一般的Bootloader是用來load os image.
BIOS、BootManager、Bootstrap、Bootloader
- 所謂的BIOS(Basic input output system 基本輸出入系統) ,是指存在主機板上的 flash ROM 上,負責許多與硬體溝通和初始化硬體的動作的,與同型號的主機緊密結合.
- 所謂BootManager(開機管理員 )寫好後,可套用在所有的 x86 機器上,大部分存在硬碟主要開機磁區(Master Boot Record, MBR)。BootManager 的工作是將OS 的核心(Kernel)載入.
- 所謂Bootstrap 就是我們利用了 BootManager 載入kernel 後,OS開始做一堆的初始動作直到我們可以開始使用,在這期間的一連串動作BootManager 也常稱為 Bootstrap Loader。
- 至於 Bootloader(開機程式)其實跟前面 所提的 BootManager 幾乎一樣(也有許多人將這兩詞視為同意),主要任務就是要讀進 kernel 使系統進入bootstrap的動作。只是在嵌入式系統中常把BIOS 與BootManager 做在一起,且也不需要選擇OS 這種功能,而把從電源一開啟到讀進 kernel 的所有動作統歸為bootloader 所負責.
Bootloader與Bootstrap如何載入與啟動Kernel?
Bootloader 為 "S1-loader"引導裝入程序, Bootstrap loader 翻譯為"S2-loader"引導裝入程序. Bootloader 不用多解釋都能理解--Power on 後執行的第一個程序,絕對不依賴kernel (Ex. u-boot、Redboot, 如下圖所述)。
Bootstrap loader: 屬於Kernel Source Code, 沒編譯進vmlinux, 但是可執行的image(如Bootable kernel image, zImage, 中含有bootstrap ),充當 Bootloader 和 kernel image 之間的glue. Bootstrap通常會check kernel、uncompress kernel、relocate kernel to ram、為kernel可以順利執行, 提供需要的環境(Interrupt cache instructions, data cache、environment setting for C language, etc.)
此外, 下列兩個head.o 不相同, Bootstrap loader用的是/arch/arm/boot/compressed/head.S, 而vmlinux用的是/arch/arm/kernel/head.S.
/arch/arm/boot/compressed/head.S:
. arch/arm/boot/compressed/head.o
ARM-specific startup code generic to ARM processors. It is this object that is passed control by the bootloader.
. arch/arm/boot/compressed/head-arm.o
Processor initialization specific to the ARM processor family. 也就是MCU的初始設定與建立C的環境.
/arch/arm/kernel/head.S:
經由bootloader轉移控制全到核心時, 就是轉移到此head.S,從此處一直進行到main.c裡的start_kernel().
P.S: 別忘了, bootloader會初始整個Embedded System, 但zImage載入到RAM時,從RAM執行的行為到核心啟動之前稱為bootstrap.
P.S: 文件中指出,CPU控制權的轉移則是由Bootload轉交的, 那麼應該可這麼說"bootstrap對於bootloader來說,應該算是bootloader中的其中一部分的行為".
/arch/arm/boot/compressed/head.S:
. arch/arm/boot/compressed/head.o
ARM-specific startup code generic to ARM processors. It is this object that is passed control by the bootloader.
. arch/arm/boot/compressed/head-arm.o
Processor initialization specific to the ARM processor family. 也就是MCU的初始設定與建立C的環境.
/arch/arm/kernel/head.S:
經由bootloader轉移控制全到核心時, 就是轉移到此head.S,從此處一直進行到main.c裡的start_kernel().
P.S: 別忘了, bootloader會初始整個Embedded System, 但zImage載入到RAM時,從RAM執行的行為到核心啟動之前稱為bootstrap.
P.S: 文件中指出,CPU控制權的轉移則是由Bootload轉交的, 那麼應該可這麼說"bootstrap對於bootloader來說,應該算是bootloader中的其中一部分的行為".
如下圖, image其实就是vmlinux.bin,vmlinux.bin的生成命令如下:
- objcopy -O binary -R .note -R .comment -S vmlinux arch/arm/boot/Image
piggy.gz(vmlinux.bin.gz)則為:
- gzip -f -9 arch/arm/boot/Image piggy.gz
配合原圖說明 kernel. make 的一個最重要的生成檔 vmlinux 去掉了、標記和注釋後生成了image. 再經過gzip壓縮後變成piggy.gz.接下來,一個名為piggy.s(將piggy.gz編譯為piggy.o)的文件被彙編成piggy.o. 最後一步,將piggy.o, misc.o, head.o 等屬於bootstrap的代碼一起鏈結成為zImage成為bootable kernel image。其中misc.o負責解壓縮、head.o head_xx.o 負責進行kernel執行環境的初始化.
最後,說明一下上面的檔案用途:
- arch/<cpu_arch>/kernel/head.S (有些平台可能在其他目录)
- Checks for valid processor and architecture
- Creates initial page table entries
- Enables the processor's memory management unit (MMU)
- Establishes limited error detection and reporting
- Jumps to the start of the kernel proper, main.c
- Kernel startup: main.c
b start_kernel
start_kernel()位于init/main.c里,是内核的第一个与平台无关的C代码起始函数。
- Architecture setup
由start_kernel()调用setup_arch(&command_line)。
回到 main.c 的啟動程序,main.c 會先呼叫 setup_arch(&command_line) 及 setup_processor() ,這裡 &command_line 是由 boot loader 設定開機參數或是寫在 kernel 裡等方法定義,可以讓 kernel 依据參數進行各種不同的啟動行為, setup_processor() 則查詢了硬體的版本及代號等訊息。
kernel_init()->init_post()-> calling /sbin/init (symbolink to busybox)
init() 會創建 PID 為 1 的第一個 user space 的 process, 再來會呼叫 /sbin/init , /etc/init 等程式(依序呼叫直到真的找到 init 這隻程式),然後就進到一般所了解的 runlevel 了。
init() 會掛起一個 ram disk,載入啟動實體 file system(ext2 等) 之前所需的 driver。
另外在嵌入式系統裡,start_kernel 跟 init() 是分別去啟動的,boot loader 會分別把兩個程式的位址記下來,然後用 bootm 進行啟動的動作,如此 kernel 才能找到 ramdisk。
&command_line再u-boot中,可能的形式如下:
setenv bootargs 'noinitrd console=ttySAC0 root=/dev/mtdblock3 rootfstype=jffs2 mtdparts=nand_flash:128k(u-boot)ro,64k(u-boot.envs),3m(kernel),30m(root.jffs2),30m(root.jffs2)'
init() 會創建 PID 為 1 的第一個 user space 的 process, 再來會呼叫 /sbin/init , /etc/init 等程式(依序呼叫直到真的找到 init 這隻程式),然後就進到一般所了解的 runlevel 了。
init() 會掛起一個 ram disk,載入啟動實體 file system(ext2 等) 之前所需的 driver。
另外在嵌入式系統裡,start_kernel 跟 init() 是分別去啟動的,boot loader 會分別把兩個程式的位址記下來,然後用 bootm 進行啟動的動作,如此 kernel 才能找到 ramdisk。
&command_line再u-boot中,可能的形式如下:
setenv bootargs 'noinitrd console=ttySAC0 root=/dev/mtdblock3 rootfstype=jffs2 mtdparts=nand_flash:128k(u-boot)ro,64k(u-boot.envs),3m(kernel),30m(root.jffs2),30m(root.jffs2)'
最後,以不講Code的方式在做一次Bootloader 與 Bootstarp的總整理(從etd-0730106-013540.pdf節錄下來)
未完,待續...
(Ref: etd-0812109-210739.pdf)
No comments:
Post a Comment