- 개요
부트로더 사전적 정의
부트로더란 운영체제가 시동되기 이전에 미리 실행되면서
커널이 올바르게 시동되기 위해 필요한 모든 관련 작업을 마무리하고
최종적으로 운영 체제를 시동시키기 위한 목적을 가진 프로그램을 말한다.
즉 임베디드 보드에 전원이 인가되었을 때, 메모리, 하드웨어(네트워크, 프로세서 속도, 인터럽트), 코드/데이터/스택 영역의 설정 및 초기화를 진행하며 커널을 메모리에 적재하여 커널을 실행시키는 역할을 한다.

임베디드 시스템에서 커널이 로딩되고 실행되는 대략적인 과정은 위와 같다.
- 부팅 정차

실제 퀄컴, 삼성 등 여러 chip 제조사들에서 제작 하는 ㅊ립 내부에 초기 부팅 과정을 수행하는 코드가 남긴다. Cpu 칩 내부에서 초기 과정을 거쳐 실제 end user 단에서 보이는 uboot 이라던지 등의 우리가 익숙한 부트로더가 수행되는 것.
====
BL2
====
BL1
====
BL0
BL0와 BL1은 Chip Vendor 사에서 제작 및 release 하는 코드 영역이다. 대표적으로 퀼컴, 삼성 등이 있으며 해당 벤더사에서 만드는 CPU가 동작하기 위한 기본 영역이라고 보면된다.
IROM : CPU 내부에 존재하는 ROM 영역
IRAM : CPU 내부에 존재하는 RAM 영역// SRAM 이라고 보면 될듯.
OM : Operation Mode으로 부팅모드를 뜻함.
-
BL0(boot-rom or boot loader))
-
iROM에 저장된 코드 영역 - ROM Code
-
크게 두가지 작업 수행
- 디바이스 환경 설정과 프라이머리 페리퍼럴의 초기화
-
OM pin으로 부터 부팅 매체를 찾아 BL1을 iRAM(SRAM)으로 읽어들인다. (OM pin은 OneNAND, NAND, MoviNAND, eSSD and iNAND 와 같은 booting device 를 결정한다.
-
이후 제어권을 BL1으로 넘김.
BL0은 칩제조사가 생산 시점에서 기록하게 된다.
-
BL(first boot lodaer, SPL)
- 일반적으로 SRAM이 U-boot와 같은 전체 부트로더를 로드하기에 충분히 크지 않기 때문에 필요한 단계.
- booting device(부팅 매체)처럼 외부 메모리에 저장 되어 있는 코드 영역.
- NAND/MMC and DRAM controller 등의 초기화 진행.
- second bootloader 로딩
- 부팅 장치(nand 나 sd 카드 ) 에 저당된 BL2를 읽어서 메모리로 로딩 & 실행.
- 이후 제어권을 BL2로 넘김.
BL1은 2차벤더가 기록하게 되며 삼성 휴대폰의 경우 삼성 모바일 사업부, ORROID의 경우 HARDKERNEL에서 책임을 담당.
-
BL2
- BL2는 일반적으로 u-boot 이나 BLOB, grub과 같은 널리 알려진 boot loder 가 사용됨.
- cpu, clock, uart, memory 등의 중요한 초기화 작업 수행.
- 커널을 dram에 올려 os loading 수행
- 커널로 제어권 넘김.

부팅흐름
- 시스템이 리셋되면 iROM 부터 PC가 시작된다.
- BL0을 수행하는 단계이다. OM pin으로부터 부팅매체를 찾아 디바이스로 부터 BL1을 iSRAM 으로 읽어드린다.
- 제어권을 넘겨받은 BL1은 BL2를 로딩한다.
- BL1을 수행하는 단계로, 부팅 장치(nand나 sd 카드)에 저장된 BL2를 읽어서 메모리로 로딩 & 실행한다.
- BL2는 일반적으로 u-boot나 BLOB,grub과 같은 널리 알려진 boot-loader 가 수행되는 단계이다.
- BL2를 수행하는 단계로 초기화 작업을 수행한 뒤 커널을 메모리에 올려 로딩한다.
- 해당 글은 ARM SECURE BOOT PROCEDURE 와 관련된 내용을 자세히 설명한다.


부팅 흐름
- ARM CPU의 전원이 켜지면 PC 레지스터가 IC에 내장된 rom 시작 부분을 가리킨다. 이 rom을 BROM(BOOTROM)이라 하며 부팅 장치의 pre loader를 찾아 isram 에 로드한다.
- BL0 단계이며 isram 에 로드하는 pre-loader 가 bl1인것 같다.
- 위 그림의 1~3 단계 설명
- Pre-lodaer가 dram을 초기화한 후 부트로더의 2단계 코드를 플래시(nand/emmc)에서 dram으로 로드하여 실행한다. 하드웨어 장치 초기화 시스템 메모리 맵 확인 커널 매개변수 설정 등을 수행한다.
- BL1를 수행하는 단계로, 부팅 장치(nand나 sd 카드)에 저장된 BL2를 읽어서 메모리로 로딩&실행 하는 과정이다.
- dram에 올라온 부팅 이미지(ramdisk,kernel 등)의 압축을 해제한 뒤 dram으로 로드하고 uboot 같은 부트로더가 수행된다.
2.3 참고자료 3

- 1단계 : ROM 코드
부팅 1 단계로 bootrom ROM 코드가 실행된다. 이후 sram 으로 작은 부트코드를 로드한다. 예를 들면 NAND 플래시 메모리, SPI를 통해 연결된 플래시 메모리, MMC 장치의 첫번째 섹터(SD 카드) 등에서 SPL을 읽는다.
- BL0 단계로 OM pin을 찾아 BL1을 isram에 올리는 과정이다. SPL이 BL1이라고 보면 될 것 같다.
- 2단계 : SPL(Secondary Program Loader)
SPL은 SRAM에서는 전체부트로더를 로드하기에는 충분히 크지 않기 때문에 필요하다. SPL은 TPL을 DRAM에 로드하도록 메모리 컨트롤러 및 필수 부분의 초기화를 수행한다. uboot.bin과 같은 알려진 파일 이름을 사용하여 프로그램을 메모리에 올린다.
- BL 단계로 BL2를 메모리에 올리는 과정이다.
- 3단계 : TPL(Tertiary Program LoadeR)
U-Boot 또는 barebox와 같은 전체 부트 로더는 간단한 명령 줄 사용자 인터페이스, 커널 이미지를 네트웍 또는 플래시 저장소에서 로드 및 부팅과 같은 유지 관리 작업을 수행한다.커널이 실행 되면 부트로더는 일반적으로 메모리에서 사라지고 시스템 작동에 더이상 참여하지 않는다.
- BL2 단계로 최종적으로 커널이 로딩되면 그 이후 제어권은 커널이 갖게된다.
System bootup overview

Samsung chip 부팅 과정
부팅과정
1. BL0 : iROM code(boot-rom)
bootrom 즉 irom에 존재하는 코드가 제일 먼저 실행된다. 이후 부팅 매체(nand, mmc, sd)를 찾아 bl1을 isram에 로드한다.
-
BL1 : first boot loader
nand/mmc, dram 컨트롤러를 초기화 하고 second boot loader 즉 bl2를 메모리에 로드한다.
-
BL2 : Second boot loader
하드웨어 초기화 및 uboot 같은 우리가 아는 부트로더가 실행되며 최종적으로 커널이 메모리에서 부팅되며 제어권을 커널로 넘긴다.

- U-boot 구조 분석
실제 우리가 아는 uboot 같은 부트로더가 실행되기 전까지 어떠한 과정을 거쳐서 부팅이 진행되는 지 살펴 보았다. uboot을 자세히 분석하자.

우선 u-boot의 디렉토리 구조를 보면 다음과 같다.
-
arch
arm, mips, powerpc 등 프로세서 아키텍처별로 서로 다른 디렉터리를 구성하고 있다. 각 아키텍처에 따른 소스를 구성하는 디렉토리. start.S 가 존재
-
board
board 와 관련된 코드. 보통 제조사가 만든 보드에 대한 코드가 존재.
-
common
u-boot에서 공통적으로 사용되는 소스를 구현한 디렉토리
-
disk
디스크 드라이버와 파티션 관련 코드 존재
-
drivers
gpio, i2c, pci, serial, usb 등 외부 장치의 드라이버 관련 코드 존재.
-
fs
u-boot에서 지원하는 다양한 파일 시스템에 대한 소스 존재.
-
lib
모든 아키텍처와 관련된 라이브러디
-
net
네트워크 관련 코드
-
post
power on self test 관련 코드
U-boot code sequence
- Disable all interrupts
- Copy any initialized data from ROM to RAM
- Zero the uninitialized data area
- Allocate space for and initialize the stack
- Initialize the processor's stack pointer
- Create and initialize the heap
- Execute the initializers for all global data
- Enable interrupts
- Call main loop
u-boot의 전체 부팅 시퀀스는 위 그림과 같다. 초기에 모든 인터럽트를 disale 시킨 뒤 ROM의 있는 데이터를 RAM으로 복사한다.
그 다음 초기화 되지 않은 영역을 초기화 시키고 스택 초기화를 진행한다. 그 다음 힙 영역과 global 영역들의 초기화 작업을 진행한 뒤 마지막으로 모든 인터럽트를 다시 enable 한 뒤 main_loop으로 이동한다. 결국 다 초기화와 관련된 작업인 것을 알 수 있다. 어떤 초기화를 수행하는 지 좀 더 자세히 살펴보자.

- Reset CPU and Hardware
start.S 파일은 uboot의 entry point이다. start.S에서는 제일 처음 여러가지 인터럽트와 예외를 처리 할 수 있는 vector table을 설정한다.
.global _start
_start : b reset // reset 함수로 분기
ldr pc, _undefined_instruction //
ldr pc, _software_interrupt //
ldr pc, _prefetch_abort //
ldr pc, _data_abort // 예외 상황에 대한 처리 handler table
ldr pc, _not_used //
ldr pc, _irq //
ldr pc, _fiq //
-
Diable IRQ & FIQ
start.S 코드에 보면 reset 함수로 제일 처음 분기를 한다. 해당 작업을 의미하는 것으로 보인다.
reset :
/*
set the cpu to SVC32 mode
/
mrs r0, cpsr
bic r0,r0,#0x1f
orr r0,r0,#0x13
msr cpsr,r0
...
- rest 함수는 주로 다음의 작업을 수행한다.
- save_boot_param
- disable FIQ & IRQ
- SVC 모드로 전환
- cpu_init_crit 함수 호출 // in lowlevel_init.S
- Low Level initialiation
- cpu_init_crit 수행
- I,D Cache 무효화
- MMU Disable
- Lowlevel_init() - 함수 호출
- lowlevel_init() - 하드웨어 초기화 역할
- uart, PMIC, 메모리 등 초기화
- board_init_f 호출
- Setup SP for Early Baord Setup Environment(ASM->C)
-
crt0.S 에 존재하는 _main 함수 호출
- setup initial stack & global data
- and jump to C rountine for board init
-
_main 내부의 board_init_f 함수 호출
- board_init_f()
- arch_cpu_init // basic arch cpu dependent setup
- board_early_init_f // early board initialization, UART pin setting
- timer_init // initilize timer
- env_init // initialize mmc/sdcard environment
- init_baudrate // initialize baudrate settings
- serial_init // serial communication setup
- console_init_f // stage 1 init of console, configure console from console.c
- display_banner // say that we are here, print u-boot banner.
- checkboard // display board info
- init_func_i2c // initialize I2C
- dram_init // configure available RAM backs
- arm_pci_init
-
board_init_f 내부에서 uboot의 text code를 memory 에 옮김.
기본적인 초기화 수행 이후 현재코드가 실행되고 있는 위치와 실제 u-boot 가 위치해야하는 주소를 비교하여 relocation 여부를 결정한다. 만약 현재 위치가 u boot 의 실제 실행 위치와 다르면 스스로를 실행위치로 복사한다.
-
start.S의 relocate code 함수 호출