Booting Process

  • Reverse Engineering from Hermit OS: ARM 부팅과 관련한 배경지식이나 레퍼런스가 x86에 비해 상대적으로 적어, arm기반의 os인 hermit-os의 부팅과정을 참조하며 제작하였다.
  • Hermit-OS의 booting process는 rust-embedded/rust-raspberrypi-OS-tutorials를 참조하여 만들어져, 이후에는 이를 참조하였다.

Hermit Booting Process

link.ld

  • Entry Point가 명시되어 있음
  • 각 섹션의 구조, 메모리상의 위치 등이 정의되어 있음
  • DTB는 0x40000000에 로딩되어 있으므로, 이를 덮어쓰지 않기 위해서 0x40200000부터 로딩하도록 함
ENTRY(_start)
phys = 0x40200000;
 
...(생략)
 
SECTIONS 
{
	. = phys;
	...(생략)
}

entry.s

_start:
	...(검증 과정 생략)
	...(초기화 과정 생략)
	
	b _start_rust
	
	...(생략)

위와 같이, 검증 및 초기화 과정을 거친 뒤에 _start_rust로 브랜치하여 rust로 제작된 코드로 점프하게 된다.

entry.rs

_start_rustpre_initloader_main

  • _start_rust: calling pre_init
  • pre_init
    • 초기화 과정 수행..
    • disable interrupts
    • reset tid registers
    • disable mmu
    • setup memory attribute type table
    • setup TCU (translation control register)
    • enable FP/ASIMD in Architectural Feature Access Control Register
    • reset debug control register
    • prepare system control register (SCTRL)
  • loader_main
    • initialize logging
    • finds kernel
    • boots kernel

Initialize Logging

  • Device Tree에서 /chosen field 의 stdout-path의 주소를 참조
  • arm의 경우 pl011 디바이스에서 stdout을 수행하는 것으로 확인됨
  • pl011의 주소는 0x09000000
  • dtb에서 0x09000000 주소를 확인하여 해당 주소에 원하는 값을 입력하면 화면에 출력된다.
chosen {
        stdout-path = "/pl011@9000000";
        rng-seed = <0x45efbb7b 0x6d473e1e 0xc4883b80 0x72c67d86 0x5215531b 0x9cb909a4 0x775c5488 0x864f215b>;
        kaslr-seed = <0x2b1e6ddd 0xe1b43dc9>;
    };

Finding Kernel

Bootloader에서 Kernel을 찾는 과정에서 메모리 정렬과 관련된 이슈로 올바르게 찾지 못하는 문제가 있어 우선 bootloader 부분을 제외한 Kernel을 바로 부팅하는 형태로 구현하였음

Reference