u-boot-2016.5 시작 프로세스

32831 단어 3u-boot
0、u-boot-2016.05\arch\arm\cpu\u-boot.lds 링크 파일ENTRY(_start)에서 알 수 있는 프로그램의 입구는start, SourceInsight에서 검색 가능한 프로그램의 입구 찾기start는 u-boot-2016.05\arch\arm\lib\vectors에 있습니다.S에서.
...

ENTRY(_start)
SECTIONS
{
    ...

    . = 0x00000000;

    . = ALIGN(4);
    .text :
    {
        *(.__image_copy_start)
        *(.vectors)
        CPUDIR/start.o (.text*)
        *(.text*)
    }

    ...

    . = ALIGN(4);
    .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

    . = ALIGN(4);
    .data : {
        *(.data*)
    }

    . = ALIGN(4);

    . = .;

    ...

    .bss_start __rel_dyn_start (OVERLAY) : {
        KEEP(*(.__bss_start));
        __bss_base = .;
    }

    .bss __bss_base (OVERLAY) : {
        *(.bss*)
         . = ALIGN(4);
         __bss_limit = .;
    }

    .bss_end __bss_limit (OVERLAY) : {
        KEEP(*(.__bss_end));
    }

    ...
}

boot-2016.05\arch\arm\lib\vectors에 들어갑니다.S에서 볼 수 있는start가 시작되면 reset으로 이동합니다:
...

.globl _start

...

_start:

#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
    .word   CONFIG_SYS_DV_NOR_BOOT_CFG
#endif

    b   reset
    ldr pc, _undefined_instruction
    ldr pc, _software_interrupt
    ldr pc, _prefetch_abort
    ldr pc, _data_abort
    ldr pc, _not_used
    ldr pc, _irq
    ldr pc, _fiq

...

1、u-boot-2016.05\arch\arm\cpu\arm920t\start.S에서 reset의 주요 실행 프로세스: reset -> cpuinit_crit -> lowlevel_init -> _main
reset:

...

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl  cpu_init_crit
#endif

    bl  _main

...

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:

...

    bl  lowlevel_init

...

#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

2,blmain에서 u-boot-2016.05\arch\arm\lib\crt0으로 이동합니다.S에서 포털로부터main에서 주요 실행 프로세스를 시작합니다:boardinit_f -> relocate_code -> board_init_r
ENTRY(_main)

        ...

    bl  board_init_f_alloc_reserve
        ...
    bl  board_init_f_init_reserve
        ...
    bl  board_init_f

#if ! defined(CONFIG_SPL_BUILD)

        ...

    b   relocate_code

        ...

#endif
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)

         ...

#if defined(CONFIG_SYS_THUMB_BUILD)

        ...

#else
    ldr pc, =board_init_r   
#endif
#endif

ENDPROC(_main)

이 부분에는 세 가지 설명이 있다. (1) u-boot-2016.05\common\boardf.c:board_init_f initcall 통과run_list(init sequence f) 함수는 전반부 보드 레벨 초기화를 위한 일련의 초기화 함수를 실행합니다.글로벌 구조체 gd는 u-boot-2016.05\arch\arm\include\asm\글로벌data.h에서 선언:
#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r9")

⑵、u-boot-2016.05\arch\arm\lib\relocate.S:relocate_코드는 uboot 코드의 재배치를 실현합니다. 이 부분은 원본 코드가 간단명료하지 않다고 생각하면 스스로 고칠 수 있습니다.(3) uboot를 다시 지정하는 데는 두 가지 경로가 있다. 하나는 gd->flags를 0으로 설정하고 함수 서열을 초기화하는 initsequence_f의 jumpto_copy 함수에서relocate 로 이동code:
static int jump_to_copy(void)
{
    if (gd->flags & GD_FLG_SKIP_RELOC)
        return 0;
    ...

#if defined(CONFIG_X86) || defined(CONFIG_ARC)
    ...
#else
    relocate_code(gd->start_addr_sp, gd->new_gd, gd->relocaddr);
#endif

    return 0;
}

다른 하나는 CONFIG 를 매크로 정의하지 않는 것이다SPL_그리고 u-boot-2016.05\arch\arm\lib\crt0.S에서 통과
#if ! defined(CONFIG_SPL_BUILD)

        ...

    b   relocate_code

        ...

#endif

relocate 로 이동code.상기 두 가지 방법 중 하나를 선택하면 다른 하나는 없애야 한다.3、이전 단계에서ldrpc를 통과,=boardinit_r명령 u-boot-2016.05\common\boardr.c:board_init_r 함수, 더 나아가 initcall 호출run_list(init sequence r) 함수는 후반부 보드 레벨 초기화를 위한 일련의 초기화 함수를 실행하고 initcallrun_list 함수에서run 입장main_loop이 다시 돌아오지 않습니다.
void board_init_r(gd_t *new_gd, ulong dest_addr)
{
    ...

    if (initcall_run_list(init_sequence_r))
        hang();

    /* NOTREACHED - run_main_loop() does not return */
    hang();
}

init_sequence_r는 함수 포인터 그룹으로 초기화 함수 포인터가 많이 저장되어 있으며 그 안에 두 가지 중요한 함수 포인터 initrannounce 및 runmain_loop:
init_fnc_t init_sequence_r[] = {

    ...

    initr_announce,

    ...

    run_main_loop,
};

initr_announce 함수 선언은 여기서부터 RAM으로 건너뜁니다.
static int initr_announce(void)
{
    debug("Now running in RAM - U-Boot at: %08lx
"
, gd->relocaddr); return 0; }

마지막은 런main_loop,run 입장main_loop 후 다시 돌아오지 않습니다.
4、runmain_loop에서 u-boot-2016.05\common\main.c:main_loop 함수
static int run_main_loop(void)
{
    ...

    for (;;)
        main_loop();
    return 0;
}

main 입장loop 이전에 초기화가 완료되었으니 명령을 처리할 준비를 하세요
/* We come here after U-Boot is initialised and ready to process commands */
void main_loop(void)
{
    const char *s;

    bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");

    ...

    /* get environment_variable: s = getenv("bootcmd"); -> bootcmd */
    s = bootdelay_process();

    ...

    autoboot_command(s);

    ...
}

main_loop 함수에는 두 가지 중요한 과정이 있다. (1) 먼저 bootdelay프로세스 함수에서 s = getenv ("bootcmd") 를 통해bootcmd 파라미터를 받아서bootcmd 파라미터를 되돌려줍니다.
const char *bootdelay_process(void)
{
    char *s;
    int bootdelay;

    ...

    s = getenv("bootdelay");

    ...

    debug("### main_loop entered: bootdelay=%d

"
, bootdelay); ... s = getenv("bootcmd"); ... stored_bootdelay = bootdelay; return s; }

여기서 bootcmd 매개 변수는 다음과 같은 방법으로 지정됩니다. 먼저 u-boot-2016.05\include\envdefault.h중
#ifdef  CONFIG_BOOTCOMMAND
    "bootcmd="  CONFIG_BOOTCOMMAND      "\0"
#endif

u-boot-2016.05\include\configs\smdk2440.h에서 지정
#define CONFIG_BOOTCOMMAND "nand read 30000000 kernel;bootm 30000000"

⑵ 그리고 autobootcommand 함수,bootcmd 매개 변수를 입력하고run 에 들어갑니다command_list 함수, bootcmd 매개 변수를 계속 전송
void autoboot_command(const char *s)
{
    ...

    if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {
        ...
        run_command_list(s, -1, 0);
        ...
    }
    ...
}

5、autoboot 에서command 함수 u-boot-2016.05\common\cli.c:run_command_list 함수 이후 board 호출run_command 함수로 명령 실행
int run_command_list(const char *cmd, int len, int flag)
{
    int need_buff = 1;
    char *buff = (char *)cmd;   /* cast away const */
    int rcode = 0;

    if (len == -1) {
        len = strlen(cmd);
#ifdef CONFIG_SYS_HUSH_PARSER
        ...
#else
        /* the built-in parser will change our string if it sees 
*/ need_buff = strchr(cmd, '
'
) != NULL; #endif } if (need_buff) { buff = malloc(len + 1); if (!buff) return 1; memcpy(buff, cmd, len); buff[len] = '\0'; } #ifdef CONFIG_SYS_HUSH_PARSER ... #ifdef CONFIG_CMDLINE ... #else rcode = board_run_command(buff); #endif #endif ... }

그럼,boardrun_command는 어떻게 명령을 실행합니까?우선,boardrun_command 함수는bootcmd 매개 변수의bootm 명령을 통해 u-boot-2016.05\cmd\bootm를 찾습니다.c의
U_BOOT_CMD(
    bootm,  CONFIG_SYS_MAXARGS, 1,  do_bootm,
    "boot application image from memory", bootm_help_text
);

그리고 이 정보에 따라bootm 명령을 실행하는 처리 함수 포인터do 를 찾습니다bootm, Do 진입bootm 함수는 관련 코드를 실행하고 UBOOT_CMD는 u-boot-2016.05\include\command.h에서 정의된 내용:
#define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help)      \
    U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, NULL)
#define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, \
                _comp)              \
    _CMD_REMOVE(sub_ ## _name, _cmd)
#define _CMD_REMOVE(_name, _cmd)                    \
    int __remove_ ## _name(void)                    \
    {                               \
        if (0)                          \
            _cmd(NULL, 0, 0, NULL);             \
        return 0;                       \
    }

여기, boardrun_command 함수는bootm 명령의 매개 변수(내부 이미지가 있는 주소) 30000000을bootm 에 부여합니다headers_t구조체 변수 images의 경우 images의 첫 주소는 30000000이고 images는 u-boot-2016.05\cmd\bootm에 있다.c에서 정의한 내용:
bootm_headers_t images; 

6、U 에 따라BOOT_CMD 정보가 u-boot-2016.05\cmd\bootm로 이동합니다.c:do_bootm 함수
int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
    ...

    return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
        BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
        BOOTM_STATE_LOADOS |
#if defined(CONFIG_PPC) || defined(CONFIG_MIPS)
        BOOTM_STATE_OS_CMDLINE |
#endif
        BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
        BOOTM_STATE_OS_GO, &images, 1);
}

여기서 BOOTMSTATE_START 、BOOTM_STATE_FINDOS 、BOOTM_STATE_FINDOTHER 、BOOTM_STATE_LOADOS 、BOOTM_STATE_OS_PREP 、BOOTM_STATE_OS_FAKE_GO 이것들은 u-boot-2016.05\include\image.h중bootmheaders 구조체에서 지정:
#define BOOTM_STATE_START   (0x00000001)
#define BOOTM_STATE_FINDOS  (0x00000002)
#define BOOTM_STATE_FINDOTHER   (0x00000004)
#define BOOTM_STATE_LOADOS  (0x00000008)
#define BOOTM_STATE_RAMDISK (0x00000010)
#define BOOTM_STATE_FDT     (0x00000020)
#define BOOTM_STATE_OS_CMDLINE  (0x00000040)
#define BOOTM_STATE_OS_BD_T (0x00000080)
#define BOOTM_STATE_OS_PREP (0x00000100)
#define BOOTM_STATE_OS_FAKE_GO  (0x00000200)    /* 'Almost' run the OS */
#define BOOTM_STATE_OS_GO   (0x00000400)

7、do 에서bootm u-boot-2016.05\common\bootm.c:do_bootm_states 함수, Now run the OS!
int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
            int states, bootm_headers_t *images, int boot_progress)
{
    boot_os_fn *boot_fn;
    ulong iflag = 0;
    int ret = 0, need_boot_fn;

    images->state |= states;

    /*
     * Work through the states and see how far we get. We stop on
     * any error.
     */
    if (states & BOOTM_STATE_START)
        ret = bootm_start(cmdtp, flag, argc, argv);

    if (!ret && (states & BOOTM_STATE_FINDOS))
        ret = bootm_find_os(cmdtp, flag, argc, argv);

    if (!ret && (states & BOOTM_STATE_FINDOTHER)) {
        ret = bootm_find_other(cmdtp, flag, argc, argv);
        argc = 0;   /* consume the args */
    }

    /* Load the OS */
    if (!ret && (states & BOOTM_STATE_LOADOS)) {
        ulong load_end;

        iflag = bootm_disable_interrupts();
        ret = bootm_load_os(images, &load_end, 0);
        if (ret == 0)
            lmb_reserve(&images->lmb, images->os.load,
                    (load_end - images->os.load));
        else if (ret && ret != BOOTM_ERR_OVERLAP)
            goto err;
        else if (ret == BOOTM_ERR_OVERLAP)
            ret = 0;
#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
        if (images->os.os == IH_OS_LINUX)
            fixup_silent_linux();
#endif
    }

    /* Relocate the ramdisk */
#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
    if (!ret && (states & BOOTM_STATE_RAMDISK)) {
        ulong rd_len = images->rd_end - images->rd_start;

        ret = boot_ramdisk_high(&images->lmb, images->rd_start,
            rd_len, &images->initrd_start, &images->initrd_end);
        if (!ret) {
            setenv_hex("initrd_start", images->initrd_start);
            setenv_hex("initrd_end", images->initrd_end);
        }
    }
#endif
#if IMAGE_ENABLE_OF_LIBFDT && defined(CONFIG_LMB)
    if (!ret && (states & BOOTM_STATE_FDT)) {
        boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr);
        ret = boot_relocate_fdt(&images->lmb, &images->ft_addr,
                    &images->ft_len);
    }
#endif

    /* From now on, we need the OS boot function */
    if (ret)
        return ret;
    boot_fn = bootm_os_get_boot_func(images->os.os);
    need_boot_fn = states & (BOOTM_STATE_OS_CMDLINE |
            BOOTM_STATE_OS_BD_T | BOOTM_STATE_OS_PREP |
            BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO);
    if (boot_fn == NULL && need_boot_fn) {
        if (iflag)
            enable_interrupts();
        printf("ERROR: booting os '%s' (%d) is not supported
"
, genimg_get_os_name(images->os.os), images->os.os); bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS); return 1; } /* Call various other states that are not generally used */ if (!ret && (states & BOOTM_STATE_OS_CMDLINE)) ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images); if (!ret && (states & BOOTM_STATE_OS_BD_T)) ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images); if (!ret && (states & BOOTM_STATE_OS_PREP)) ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images); #ifdef CONFIG_TRACE /* Pretend to run the OS, then run a user command */ if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) { char *cmd_list = getenv("fakegocmd"); ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO, images, boot_fn); if (!ret && cmd_list) ret = run_command_list(cmd_list, -1, flag); } #endif /* Check for unsupported subcommand. */ if (ret) { puts("subcommand not supported
"
); return ret; } /* Now run the OS! We hope this doesn't return */ if (!ret && (states & BOOTM_STATE_OS_GO)) ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO, images, boot_fn); /* Deal with any fallout */ err: if (iflag) enable_interrupts(); if (ret == BOOTM_ERR_UNIMPLEMENTED) bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL); else if (ret == BOOTM_ERR_RESET) do_reset(cmdtp, flag, argc, argv); return ret; }

do_bootm_states 함수는 총 8개 부분으로 나뉜다. (1) Work through the states and see how far we get.We stop on any error. 여기서 주요 함수 bootmfind_os는 get kernel image header, start address and length, get image parameters 세 가지 기능을 실현한다.대략적인 과정은:bootmfind_os -> boot_get_kernel -> image_get_kernel .
static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
             char * const argv[])
{
    const void *os_hdr;
    bool ep_found = false;
    int ret;

    /* get kernel image header, start address and length */
    os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
            &images, &images.os.image_start, &images.os.image_len);
    ...

    /* get image parameters */
    switch (genimg_get_format(os_hdr)) {
#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
    case IMAGE_FORMAT_LEGACY: /*          */
        images.os.type = image_get_type(os_hdr);
        images.os.comp = image_get_comp(os_hdr);
        images.os.os = image_get_os(os_hdr);

        images.os.end = image_get_image_end(os_hdr);
        images.os.load = image_get_load(os_hdr);
        images.os.arch = image_get_arch(os_hdr);
        break;
#endif
#if IMAGE_ENABLE_FIT
    case IMAGE_FORMAT_FIT:
        ...
#endif
#ifdef CONFIG_ANDROID_BOOT_IMAGE
    case IMAGE_FORMAT_ANDROID:
        ...
#endif
    default:
        puts("ERROR: unknown image format type!
"
); return 1; } ... if (images.os.type == IH_TYPE_KERNEL_NOLOAD) { images.os.load = images.os.image_start; images.ep += images.os.load; } ...

boot 정보get_kernel 、image_get_kernel의 설명: bootget_kernel - find kernel image(returns: pointer to image header if valid image was found, plus kernel start address and length, otherwise NULL)
image_get_kernel - verify legacy format kernel image(returns: pointer to a legacy image header if valid image was found otherwise return NULL) ⑵, Load the OS 37108;, Relocate the ramdisk ⑳, From now on, we need the OS boot function은 boot_fn = bootm_os_get_boot_func(images->os.os); boot 처리 함수 포인터를 받아서 bootfn. ①、매개 변수에 대한 이미지s->os.os, 다음 정의에서 알 수 있듯이 이것은 시스템 내 핵의 유형이고 (2)에 값이 부여됩니다. 만약 시스템 유형이 linux라면images->os입니다.os=5.
typedef struct bootm_headers {

    ...

#ifndef USE_HOSTCC  /*USE_HOSTCC      */
    image_info_t    os;     /* os image info */
    ulong       ep;     /* entry point of OS */

    ulong       rd_start, rd_end;/* ramdisk start/end */

    char        *ft_addr;   /* flat dev tree address */
    ulong       ft_len;     /* length of flat device tree */

    ulong       initrd_start;
    ulong       initrd_end;
    ulong       cmdline_start;
    ulong       cmdline_end;
    bd_t        *kbd;
#endif

    ...

} bootm_headers_t;
bootm_headers_t images;
typedef struct image_info {
    ulong       start, end;     /* start/end of blob */
    ulong       image_start, image_len; /* start of image within blob, len of image */
    ulong       load;           /* load addr for the image */
    uint8_t     comp, type, os;     /* compression, type of image, os type */
    uint8_t     arch;           /* CPU architecture */
} image_info_t;

이미지 가져오기os.os 값:
static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
             char * const argv[])
{
    const void *os_hdr;

    ...

    /* get kernel image header, start address and length */
    os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
            &images, &images.os.image_start, &images.os.image_len);

    ...

    /* get image parameters */
    switch (genimg_get_format(os_hdr)) {
#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
    case IMAGE_FORMAT_LEGACY:                       /*          */
        ...
        images.os.os = image_get_os(os_hdr);
        ...
        break;
#endif

②、bootm_os_get_boot_func에서 함수 포인터 배열 boot 사용os, 이 수조는 전송된 이미지를 이용한다.os.os=5의 boot 처리 함수 포인터dobootm_boot 에 linux 반환fn .
boot_fn = bootm_os_get_boot_func(images->os.os);
boot_os_fn *bootm_os_get_boot_func(int os)
{
    ...
    return boot_os[os];
}
static boot_os_fn *boot_os[] = {
    [IH_OS_U_BOOT] = do_bootm_standalone,
#ifdef CONFIG_BOOTM_LINUX
    [IH_OS_LINUX] = do_bootm_linux,
#endif
#ifdef CONFIG_BOOTM_NETBSD
    [IH_OS_NETBSD] = do_bootm_netbsd,
#endif
    ...
};

운영 체제 코드는 u-boot-2016.05\include\image.h에서 보기
/*
 * Operating System Codes
 */
#define IH_OS_INVALID       0   /* Invalid OS   */
#define IH_OS_OPENBSD       1   /* OpenBSD  */
#define IH_OS_NETBSD        2   /* NetBSD   */
#define IH_OS_FREEBSD       3   /* FreeBSD  */
#define IH_OS_4_4BSD        4   /* 4.4BSD   */
#define IH_OS_LINUX     5   /* Linux    */

        ...

⑸、Call various other states that are not generally used ⑹、Check for unsupported subcommand ⑺、Now run the OS! We hope this doesn’t return
if (!ret && (states & BOOTM_STATE_OS_GO))
        ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO,
                images, boot_fn);

Dobootm_states u-boot-2016.05\common\bootm 진입os.c:boot_selected_os 함수, 실행boot_fn(state, argc, argv, images);
int boot_selected_os(int argc, char * const argv[], int state,
             bootm_headers_t *images, boot_os_fn *boot_fn)
{
    ...
    boot_fn(state, argc, argv, images);
    ...
}

⑻, Deal withany fallout 8, 실행boot_fn(state, argc, argv, images), 왜냐하면bootfn=do_bootm_루스, 그래서 실행do_bootm_linux(state, argc, argv, images)에 해당, 프로그램은 u-boot-2016.05\arch\arm\lib\bootm로 넘어갑니다.c:
/* Main Entry point for arm bootm implementation*/
int do_bootm_linux(int flag, int argc, char * const argv[],
           bootm_headers_t *images)
{
    ...
    boot_jump_linux(images, flag);
    ...
}

do_bootm_linux -> boot_jump_linux -> kernel_entry(0, machid, r2);
static void boot_jump_linux(bootm_headers_t *images, int flag)
{
    ...

    unsigned long machid = gd->bd->bi_arch_number;
    char *s;
    void (*kernel_entry)(int zero, int arch, uint params);
    unsigned long r2;
    int fake = (flag & BOOTM_STATE_OS_FAKE_GO);

    kernel_entry = (void (*)(int, int, uint))images->ep; /* ep:entry point of OS*/

    s = getenv("machid");
    if (s) {
        if (strict_strtoul(s, 16, &machid) < 0) {
            debug("strict_strtoul failed!
"
); return; } printf("Using machid 0x%lx from environment
"
, machid); } ... if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) r2 = (unsigned long)images->ft_addr; else r2 = gd->bd->bi_boot_params; if (!fake) { ... kernel_entry(0, machid, r2); } #endif }

run the OS! 설명: kernel_entry = (void (*)(int, int, uint))images->ep;의 images->ep가 u-boot-2016.05\common\bootm.c:bootm_find_os 함수에 값이 부여되었습니다.
static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
             char * const argv[])
{
    ...

    if (images.os.type == IH_TYPE_KERNEL_NOLOAD) {
        images.os.load = images.os.image_start;
        images.ep += images.os.load;
    }

    ...
}

좋은 웹페이지 즐겨찾기