# 開機程序 (Booting Process)
###### tags: `Hardware` `Embedded System` `Bootstrap` `Bootloader` `MCU` `SoC` `x86` `ARM` `Linux` `Kernel` `GRUB` `Operating System` `Computer Architecture`
筆記彙整現今在不同硬體 (PC, MCU, SoC)、指令集 (x86, ARM)、作業系統類型 (Bare Metal, RTOS, GPOS) 上的多樣開機程序和技術。
![image](https://hackmd.io/_uploads/H1O7RvMd0.png)
## Boot Process Overview
![](https://yt3.ggpht.com/Qd6wVM264FQCQvs_P4PSKtruDkhfD64thJ6vble0nTyhlSR8P7OCvZR0rodNrlUJ50EU8AVhjLu1=s1600-nd-v1-rwa-mo =400x)
Refs:
- [第二十章、開機流程、模組管理與 Loader - for CentOS 5.x - 鳥哥私房菜](https://linux.vbird.org/linux_basic/centos5/0510osloader-centos5.php)
- [開機流程與GRUB](http://teaching.idv.tw/Course/joelinux/article/grub.html)
- [Linux System Administrators Guide: Chapter 8. Boots And Shutdowns](https://tldp.org/LDP/sag/html/boots-and-shutdowns.html)
- [CSE 506 Lab 4 - Multiprocessor Support 筆記 - Cherie Hsieh](https://yushuanhsieh.github.io/post/2021-04-23-life/)
### 0th Step: Booting from ROM (BIOS, UEFI, BootROM)
電路上的 reset 訊號觸發,將 ROM (EEPROM, NOR FLASH) 上的 Code 搬運到 Processor 中執行 (進階設定如:起始位址區塊, ... 可由硬體撥桿或韌體設定)
> 主要進行簡單初始化工作後,將執行權交給 1st BootLoader。
#### 主要工作
- 關閉 / 重設[看門狗計時器](https://zh.wikipedia.org/zh-tw/%E7%9C%8B%E9%96%80%E7%8B%97%E8%A8%88%E6%99%82%E5%99%A8)
![image](https://hackmd.io/_uploads/Sy0LOhKV0.png =300x)
- 初始化 exception/interrupt handler table、時鐘、通訊、基礎驅動、POST(Power-On Self Test)
- 初始化存儲、DMA、校驗、驗證、解壓、更新 ... 等服務
![image](https://hackmd.io/_uploads/rkfdK0KER.png =400x)
#### Multiprocessor
1. 由 BIOS 或硬體指派某一核心為 Bootstrap Processor (BSP),其他核心則為 Application Processor (AP)。
2. BIOS 喚醒 BSP 執行 booting 程序。
3. BSP 從 BIOS 讀取多核心參數。
4. BSP 再透過 Interprocessor Interrupt (IPI) 喚醒其他 AP 執行 booting 程序,將欲執行的 reset code (bootloader) 的位址 reset vector (reset address) 寫入 AP 的 LAPIC (local advanced programming interrupt controller) 的 register。
1. BSP 發送 IPI: INIT。
2. BSP 發送 IPI: STARTUP。
3. AP 初始化: 設定 exception vectors、啟用 LAPIC interrupt、認識系統周遭環境 (已被 BSP 初始化)、...
6. BSP polling 直到 AP 的 state 改變。
#### MCU (ARM Cortex)
沒有 MMU、大多 single core 或 SMP 運行在低頻率、運行 RTOS 且 Processor 可直接讀取 ROM 上的 code 執行 (無須 RAM 參與)。之後在 1st bootloader 中便可執行更完整的客製化檢測及初始化服務。
More:
- [整合RTOS運行防護 TrustZone強化物聯網安全 - Joseph Yiu](https://www.2cm.com.tw/2cm/zh-tw/tech/C99CAB2F8A9944D080ECFDC7348AA3F1)
![image](https://hackmd.io/_uploads/HkdDVAK40.png =400x)
- :+1: [燒錄單體 MCU,從 BootLoader 燒錄器開始,製作完整的 Arduino 控制器。 - 阿吉米德](https://www.youtube.com/watch?v=TI4SC3Zi6pI)
#### SoC
作業系統 x 檔案系統 x 驅動應用 打包放在 Nand flash 中,首先先將 SPL (Secondary Program Loader) 載入侷促的 SRAM 空間中並跳轉執行,以開始初始化 DRAM 及後續必要環境之工作,再將 uboot 搬進 DRAM 並跳轉執行,再邊解壓邊將真正作業系統及檔案系統 ... 載入。
### 1st Step: 1st Stage BootLoader (on MBR, GPT Sector)
[Master Boot Record (MBR)](https://zh.wikipedia.org/zh-tw/%E4%B8%BB%E5%BC%95%E5%AF%BC%E8%AE%B0%E5%BD%95) vs. [GUID Partition Table (GPT)](https://zh.wikipedia.org/zh-tw/GUID%E7%A3%81%E7%A2%9F%E5%88%86%E5%89%B2%E8%A1%A8)
> Stage I 通常會置放於MBR,即446bytes的位置,但也可以直接置於獨立 /boot 的第一個sector (每 OS 各一個),稱為boot sector,此sector因容量過小,只有512 bytes,所以大部分程式碼在Stage II執行
### 2nd Step: 2nd Stage BootLoader (GRUB, LILO)
> 最有名的Stage II 大概算是GRUB及LILO了,它們提供選單,以讓使用者在開機時可以選擇用哪個OS開機。從此,boot loader就交給OS 的 kernel 進行第三階段工作。
#### GRUB vs. LILO
LILO沒有CLI介面可下指令,所有開機參數都寫在設定檔(/etc/lilo.conf)及MBR裡,萬一參數有錯,則系統將無法順利開機,得使用具開機修護功能的floppy 來補救。
GRUB (GRand Unified Bootloader)是管理開機的Boot Loader管理程式,與早期LILO角色相當,但因它具較多功能,早在RH9時代就已取代 LILO成為預設Boot Manager。
- **/boot/grub/grub.conf**
*用於開機設定檔*
```=
password --md5 $1$H2GMv1$7l/WWRBL/Vb1AkFeQx8ti1 # 進入GRUB畫面,要 md5 hash 密碼
splashimage=(hd0,0)/grub/splash.xpm.gz # GRUB Splash 顯示的 splash.xpm.gz 圖檔
hiddenmenu # stanza的內容將不會被顯示在開機時
title CentOS (2.6.18-92.el5) # stanza 0的開始,標籤名稱
root (hd0,0) # 下面所列的檔案都以hd0,0為參考點
kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/ # kernel檔及root filesystem
initrd /initrd-2.6.18-92.el5.img # 要載入執行的RAM DISK檔
title Windows XP # stanza 1的標籤
rootnoverify(hd0,1) # root是 hd0,1,不要 mount在GRUB
chainloader +1 # 由hd0,1第一sector來開機
```
More:
- [Ubuntu GRUB Linux Bootloader and Configuration - Sagar](https://adamtheautomator.com/ubuntu-grub/)
### 3rd Step: Kernel Init
進行一切必要裝置探索、載入、檢查、初始化後,在基礎 driver 都就緒後,kernel 重新起始所有裝置,並根據 grub.conf 檔以建立 root 裝置,掛載 readonly 的 root partition。最後再交給 init process 來創造可執行 user program 之作業環境。
> 由於一開始可能會用到 SCSI 及 RAID 設備,必須先在 RAM disk 中先驅動它,且這些 driver 可能都以外掛模組獨立 kernel 之外,因此需要 initrd 這個暫時性 image。
More:
- [initramfs原理探讨:为什么需要initramfs -《深度探索Linux操作系统 : 系统构建和原理解析》 学习笔记 - vita](https://yifengyou.github.io/vita/docs/%E6%9E%84%E5%BB%BAinitramfs/initramfs%E5%8E%9F%E7%90%86%E6%8E%A2%E8%AE%A8.html)