리눅스 디바이스 트리: 커널 포팅

리눅스 커널 부트 프로세스

uboot는 bootcmd 명령어를 통해 커널을 실행합니다:

bootcmd="nand read 0x30000000 kernel; bootm 0x30000000"

uboot는 NAND에서 커널 이미지를 0x30000000 메모리 주소로 복사한 후 bootm 명령을 실행합니다.

bootm 명령 처리

bootm은 운영체제 맵을 시작하는 함수로, arch/arm/lib/bootm.c의 do_bootm_linux 함수를 호출합니다:

int handle_boot_linux(int flags, int count, char * const args[], 
           boot_headers_t *img)
{
    if (flags & BOOTM_STATE_OS_BD_T || flags & BOOTM_STATE_OS_CMDLINE)  
        return -1;

    if (flags & BOOTM_STATE_OS_PREP) {
        prepare_linux_boot(img);
        return 0;
    }

    if (flags & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
        jump_to_linux(img, flags);
        return 0;
    }

    prepare_linux_boot(img);
    jump_to_linux(img, flags);
    return 0;
}

prepare_linux_boot는 부트 파라미터 설정을 담당하며, jump_to_linux는 태그 주소(gd->bd->bi_boot_params)를 커널에 전달합니다.

점프 메커니즘

static void jump_to_linux(boot_headers_t *img, int flags)
{
    unsigned long machine_id = gd->bd->bi_arch_num;
    void (*kernel_start)(int zero, int arch, uint params);
    unsigned long param_addr;
    int simulated = (flags & BOOTM_STATE_OS_FAKE_GO);

    kernel_start = (void (*)(int, int, uint))img->entry;

    if (IMAGE_ENABLE_OF_LIBFDT && img->fdt_length)  
        param_addr = (unsigned long)img->fdt_addr;
    else
        param_addr = gd->bd->bi_boot_params;

    if (!simulated) {
         kernel_start(0, machine_id, param_addr);
    }
}

디바이스 트리 사용 시 param_addr은 dtb 시작 주소로 설정됩니다.

디바이스 트리 포팅

Linux 5.2.8 소스코드를 기반으로 Mini2440용 디바이스 트리를 구성합니다.

커널 설정

Makefile 수정:

ARCH        ?= arm
CROSS_COMPILE    ?= arm-linux-

s3c2440_defconfig 생성:

cp arch/arm/configs/s3c2410_defconfig arch/arm/configs/s3c2440_defconfig

디바이스 트리 추가

DTS 파일 생성:

cp s3c2416.dtsi s3c2440.dtsi
cp s3c2416-pinctrl.dtsi s3c2440-pinctrl.dtsi
cp s3c2416-smdk2416.dts s3c2440-smdk2440.dts

Makefile에 타겟 추가:

dtb-$(CONFIG_ARCH_S3C24XX) += s3c2440-smdk2440.dtb

하드웨어 지원 설정

Kconfig에 ARCH_S3C2440_DT 옵션 추가:

config ARCH_S3C2440_DT
    bool "MINI2440 with devicetree"
    select TIMER_OF
    select USE_OF
    select PINCTRL
    select PINCTRL_S3C24XX

매칭 머신 파일 생성 (mach-smdk2440-dt.c):

static const char *const s3c2440_dt_compat[] __initconst = {
    "samsung,s3c2440",
    "samsung,mini2440",
    NULL
};

DT_MACHINE_START(S3C2440_DT, "Samsung S3C2440 (Flattened Device Tree)")
    .dt_compat = s3c2440_dt_compat,
    ...

커널 최적화

menuconfig 설정:

Boot options → Flattened Device Tree support
Device Drivers → Network → Ethernet → DM9000 support
File systems → Network File Systems → NFS client
Kernel hacking → Early printk
Kernel Features → ARM EABI

U-Boot FDT 지원

uboot 설정 파일에 추가:

CONFIG_OF_LIBFDT=y

부트 명령:

tftp 0x30001000 s3c2440-smdk2440.dtb
tftp 0x30008000 uImage
bootm 0x30008000 - 0x30001000

태그: 디바이스트리 리눅스커널 ARM포팅 U-Boot 디바이스드라이버

7월 22일 12:07에 게시됨