u-boot코드의 큰 흐름은

1. U-boot.lds에서 ENTRY에 지정된 "_start"함수로 u-boot프로그램이 시작된다.

2. start.s에서 "_start"가 실행되고 "b     reset"에 의해 reset으로 제어가 넘어간다.

3. reset함수에서는

    1) CPU를 supervisor mode로 set시키고

    2) watchdog를 trun off시키고

    3) interrupt를 disable시키고

    4) CPU clock을 셋팅한다.

    5) "cpu_init_crit"에 의해 memsetup.s로 분기되고 메모리를 초기화 한후 start.s로 돌아와

4. armboot를 RAM으로 재배치한다.

5. stackpoint를 설정해 주었으므로 C routine을 실행하기위해 board.c에 포함되어있는 start_armboot()로 branch한다.

6. board.c에서 board에 관련된 모든자원을 초기화하고 main()함수로 이동하게 된다.

 

 

이는 외울 필요없이 코드를 따라가보면 나오는 것이고, 부팅절차를 생각해보면 자연스러운 흐름이다.

 

 

 

그럼 먼저 U-boot.lds를 보도록 하겠다.

 

 

/*
 *      A     EEEE  SSSS   OOO  PPPP
 *     A A    E     S     O   O P   P
 *    AAAAA   EEEE  SSSS  O   O PPPP
 *   A     A  E         S O   O P
 *   A     A  EEEE  SSSS   OOO  P
 *
 *  An Entertainment Solution On a Platform (AESOP) is a completely Open Source
 *  based graphical user environment and suite of applications for PDAs and other
 *  devices running Linux. It is included in various embedded Linux distributions
 *  such as OpenZaurus -
http://www.aesop-embedded.org
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *
 * Title           : u-boot.lds
 * Author          :
 * Created date    : 2005. 06. 26. 23:07:07 KST
 * Description     :
 *
 * $Revision: 1.1.1.1 $
 * $Log: u-boot.lds,v $
 * Revision 1.1.1.1  2005/06/27 17:04:29  linuxpark
 * Initial import.
 * 
 * 
 *
 */

/*
 * (C) Copyright 2002
 * Gary Jennejohn, DENX Software Engineering, <
gj@denx.de>
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 
      /* elf32의  little endian으로 코드를 생성하겠다. */
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm)  /* binary를 실행할 수 있는 CPU Architecture로 Arm을 사용하겠다 */
ENTRY(_start)    /* u-boot 프로그램의 시작.  시작되는 함수의 이름은 "_start". 여기에서 _start로 제어가 넘어간다.*/
SECTIONS
{
 . = 0x00000000;

 . = ALIGN(4); /* 프로그램 코드는 0x00000000에서 4byte단위로 정렬된 text section에 놓여질 것이다. */
 .text      :
 {
   cpu/arm920t/start.o (.text)
   *(.text)
 }

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

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

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

 __u_boot_cmd_start = .;
 .u_boot_cmd : { *(.u_boot_cmd) } //user interface command stucture를 여기에 배치해라.
 __u_boot_cmd_end = .;

 . = ALIGN(4);
 __bss_start = .;  
 .bss : { *(.bss) }  //bss <= global 변수 중에서 0으로 초기화 되지 않은 영역.
 _end = .;
}

 

---------------

출처 : http://blog.naver.com/idrukawa/100054112166

U-Boot는 정말 거대한 프로그램이다.  이런 큰 프로그램은 분석하는 것조차 눈이 빠질 지경이다.  image없이 *.c, *.h, *.o 등등 text파일로만 23Mbyte를 육박한다.  폴더만 110개 가량 파일수는 1300개 이상이다.  이런 거대한 프로그램을 어디서 시작해서 그 함수들은 어떻게 쫓아가면서 분석을 해야할까??  이것역시 큰 고민이고 일이다. 

 

해서 우선은 분석프로그램을 하나 소개할까한다.  이는 멘토인 김남호 수석연구원님이 알려준 분석프로그램으로 source insight라는 프로그램이다.  사용법은 비교적 쉽다.  우선 프로젝트를 생성하여 그 분석하고자 하는 프로그램의 폴더 및 파일을 프로젝트에  추가한다.  필자의 경우 aesop2440보드를 사용할 것이므로 이솝사이트에서 받은 u-boot프로그램을 프로젝트에 추가했다.  그리고 source insight의 오른쪽부분에 검색창에서 분석하고자 하는 파일의 이름을 치면 아래로 목록이 쫙~ 뜬다.  파일을 선택하면 왼쪽의 넓은 창에서 분석을 하면된다.  소스에서 호출된 함수나 정의된 메크로등은 마우스로 클릭하거나 ctrl+더블클릭을 하게되면 선택된 영역과 같은 이름을 갖는 함수정의나 호출부분이 프로젝트전체에서 검색되어져 링크창으로 팝업이되고 쉽게 어떻게 정의된 함수인지 확인할 수 있다.

 

 

p.s> aesop보드용 2440 U-Boot입니다.

            http://www.aesop-embedded.org/sw/u-boot-1.1.2-aesop2440.tar.gz

 

       U-Boot입니다.  각자의 보드에 맞게 수정을 요합니다.

            http://sourceforge.net/projects/u-boot

 

       source insight홈페이지를 링크로 걸겠습니다.

            http://sourceinsight.com

출처 : http://blog.naver.com/idrukawa/100054094629

OPERATING MODE REGISTER (OMR, R, ADDRESS = 0XE000_0004)

Field Bit Description Reset Value

Reserved [31:18] Read as zero 0x0

Reserved [17] Read as one 1

Reserved [16] Read as one 1

Reserved [15:14] Read as zero 0x0

NFMOD [13:8] The value of the XNFMOD[5:0] pad Pin value

Reserved [7:5] Read as zero 0x0

OM [4:0] The value of the XOM[4:0] pad Pin value

 

 

OM[4]:

0 = normal mode, 1 = test mode

 

OM[3]:

0 = 1st boot loader in iROM , 1 = reserved

 

OM[2:1] :

00 = 2nd boot loader in NAND flash

01 = 2nd boot loader in OneNAND

10 = 2nd boot loader in MMC

11 = Reserved

 

OM[0] : APLL/MPLL input selection

0 = XXTI

1 = XusbXTI


< hkdkc100\config.mk 파일에서 >
ifndef TEXT_BASE
//TEXT_BASE = 0xc7e00000
TEXT_BASE = 0x27e00000
endif

< hkdkc100.h(45) 파일에서>
#define CONFIG_S5PC100_EVT2
#define BOOT_ONENAND        0x1
#define BOOT_NAND              0x2
#define BOOT_MMCSD          0x3

#undef CONFIG_ENABLE_MMU
#define CONFIG_MEMORY_UPPER_CODE
#undef CONFIG_USE_IRQ                /* we don't need IRQ/FIQ stuff */

< cpu/s5pc1xx/start.s 파일에서 >

///////////////////////////////////////////////////////////////
        /* Read booting information *
        ldr        r0, =PRO_ID_BASE        ; PRO_ID_BASE = 0XE000_000
        ldr        r1, [r0,#OMR_OFFSET] ; OMR_OFFSET = 0x04
        bic       r2, r1, #0xfffffff9

        cmp      r2, #0x0
        moveq   r3, #BOOT_NAND

        cmp      r2, #0x2
        moveq   r3, #BOOT_ONENAND

        cmp       r2, #0x4
        moveq    r3, #BOOT_MMCSD

    ldr    r0, =INF_REG_BASE
    str    r3, [r0, #INF_REG3_OFFSET]    
     
    /*
     * Go setup Memory and board specific bits prior to relocation.
     */
    bl    lowlevel_init    /* go setup pll,mux,memory */

    /* when we already run in ram, we don't need to relocate U-Boot.
     * and actually, memory controller must be configured before U-Boot
     * is running in ram.
     */
    ldr    r0, =0xff000fff
    bic    r1, pc, r0        /* r0 <- current base addr of code */
    ldr    r2, _TEXT_BASE        /* r1 <- original base addr in ram */
    bic    r2, r2, r0        /* r0 <- current base addr of code */
    cmp     r1, r2                  /* compare r0, r1                  */
    beq     after_copy        /* r0 == r1 then skip flash copy   */

    ldr    r0, =INF_REG_BASE
    ldr    r1, [r0, #INF_REG3_OFFSET]
    cmp    r1, #BOOT_NAND        /* 0x0 => boot device is nand */
    beq    nand_boot
    cmp    r1, #BOOT_ONENAND    /* 0x1 => boot device is onenand */
    beq    onenand_boot
    cmp     r1, #BOOT_MMCSD
    beq     mmcsd_boot

출처 : http://blog.naver.com/serimo/50091184494
< cpu/s5pc1xx/start.s 파일에서 >
       /*
        * disable MMU stuff and caches
        */
        mrc    p15, 0, r0, c1, c0, 0
        bic    r0, r0, #0x00002000     @ clear bits 13 (--V-)
        bic    r0, r0, #0x00000007     @ clear bits 2:0 (-CAM)
        orr    r0, r0, #0x00000002     @ set bit 1 (--A-) Align
        orr    r0, r0, #0x00000800     @ set bit 12 (Z---) BTB
        mcr     p15, 0, r0, c1, c0, 0

출처 : http://blog.naver.com/serimo/50091184301

<MCR|MRC>{cond}p#,<expression1>,Rd,cRn,cRm{,<expression2>}

MRC : coprocessor registerCPU register로 이동 (L=1)

MCR : CPU register coprocessor register로 이동 (L=0)

{cond} : Two character condition mnemonic

p# : coprocessor 번호

<opcode_1> : coprocessor-specific opcode. <opcode_1> 은 항상 0 이다.

Rd : CPU register number

cRn and cRm : coprocessor register numbers

<opcode_2> : coprocessor-specific opcode. 이 필드는 생략 할 수 있다.


< cpu/s5pc1xx/start.s 파일에서 >

/*
 *************************************************************************
 *
 * CPU_init_critical registers
 *
 * setup important registers
 * setup memory timing
 *
 *************************************************************************
 */
         /*
         * we do sys-critical inits only at reboot,
         * not when booting from ram!
         */
cpu_init_crit:
        /*
        * Invalidate L1 I/D
        */
        mov    r0, #0                      @ set up for MCR

        mcr    p15, 0, r0, c8, c7, 0   @ invalidate TLBs
// 1. 변환 참조 버퍼(Transition Lockaside Buffer: TLB)를 무효화

        mcr    p15, 0, r0, c7, c5, 0   @ invalidate icache
// 2. 명령어 캐시(instruction cache: I-cache) 무효화

출처 : http://blog.naver.com/serimo/50091160857

ARM에 리셋 신호가 입력이 되면 리셋 예외처리가 발생한다. 리셋은 전원을 처음 연결하거나 리셋 스위치를 누를 경우 발생한다.

1.     ARM 상태로 전환( CPRS[5] = 0 )

2.     인터럽트 중지 ( FIQ disable : CPRS[6] = 1, IRQ disable : CPRS[7] = 1)

3.     SVC 모드로 전환( CPRS[4:0] = 10011 )

4.     어드레스 0x0 번지로 분기하여 리셋 핸들러를 처리한다.

따라서 시스템의 0x0 번지는 Linker script file( U-boot.lds)의 Entry point에서 선언된 '_start'가 되고 여기서 부터 코드가 실행되어 reset으로 분기, 시스템의 부팅 처리를 수행한다.

다음은 부트로더의 reset 핸들 러에서 처리하는 코드이다.

< cpu/s5pc1xx/start.s 파일에서 >

/*
 *************************************************************************
 *
 * Jump vector table as in table 3.1 in [1]
 *
 *************************************************************************
 */

.globl _start
_start: 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

_undefined_instruction:
    .word undefined_instruction
_software_interrupt:
    .word software_interrupt
_prefetch_abort:
    .word prefetch_abort
_data_abort:
    .word data_abort
_not_used:
    .word not_used
_irq:
    .word irq
_fiq:
    .word fiq
_pad:
    .word 0x12345678 /* now 16*4=64 */
.global _end_vect
_end_vect:

    .balignl 16,0xdeadbeef


/*
 * the actual reset code
 */

reset:
    /*
     * set the cpu to SVC32 mode and IRQ & FIQ disable
     */

    mrs      r0, cpsr           

    bic       r0, r0, #0x1F      @ r0 레지스터의 0x1F 비트들을 비트 클리어한다.

    orr       r0, r0, #0xD3     @ 1101 0011 : ARM상태전환, 인터럽트 중지, SVC모드전환

                                   @ 0xD3 비트를 OR 한다.

    msr      cpsr, r0

 
* ARM의 상태 레지스터(PSR)

상태 레지스터는 1개 의 CPSR 5개의 SPSR로 구성되어 있고 내부 구조는 서로 동일하다.


비 트

명 칭

분 류

의 미

CPSR[4:0]

모드비트

컨트롤 비트

프로세서의 동작모드를 의미한다.

10000   User 모드

10001   FIQ 모드

10010   IRQ 모드

10011   SVC 모드

10111   Abort 모드

11011   Undefined 모드

11111   System 모드

CPSR[5]

상태비트( T )

ARM 아키텍쳐에서 16비트 명령인 Thumb 명령을 실행할 수 있는 상태인 경우를 1 Thumb상태, 0인 경우는 ARM 상태를 의미한다

CPSR[6]

FIQ

비트가 1로 설정되어 있으면 disable, 0이면 Enable

CPSR[7]

IRQ

비트가 1로 설정되어 있으면 disable, 0이면 Enable

CPSR[24]

J bit

컨디션코드 플래그

새로운 ARM 아키텍쳐에서 JAVA 바이트 코드 명령이 가능한데 JAVA 명령 실행 상태이면 설정된다

CPSR[27]

Q flag(Q)

새로운 ARM 아키텍쳐에서 추가된 포화 연산 명령의 수행결과 포화상태가 발생하면 설정된다. 사용후 반드시 클리어를 해 주어야 한다

CPSR[28]

Overflow( V )

연산결과가 오버플로우가 되었을 때 설정된다

CPSR[29]

Carry flag( C )

자리올림이나 내림이 발생한 경우, Shift 연 산에서 캐리가 발생한

경우에 설정된다

CPSR[30]

Zero( Z )

연산결과가 0인 경우에 설정된다

CPSR[31]

Negative( N )

연산 결과가 값인 경우에 설정된다


상태 레지스터(PSR) 전송 명령어

상태 레지스터(PSR)CPSRSPSR 2 종류가 있다. PSR 전송명령이란 이 2종류의 레지스터와 범용 레지스터들( R0 ~ R15 )과 의 데이터 전송을 하는 명령이다.


CPSR User모드에서는 컨디션코드 플래그만 쓰기가 가능하고 그 외 모든 특권모드에서는 모든 필드에 쓰기가 가능하다.

SPSR User 모드에서는 정의되어 있지 않고 각 특권 모드의 해당 SPSR만 엑세스가 가능하다.


MRS 명령

CPRS SPRS 레지스터 값을 ARM의 범용 레지스터로 읽어오는 명령이다.

MRS r0, cpsr   @ CPSRr0에 전송한다.

 

MSR 명령

ARM의 범용 레지스터나 상수값을 CPRS SPRS 레지스터에 쓰는 명령이다.

MSR cpsr, r0   @ r0CPSR에 전송한다.

출처 : http://blog.naver.com/serimo/50091044696
출처 : http://blog.naver.com/serimo/50091042306

 

명령어 타입

명령

1

Branch, 링크 Branch

B, BL

2

Branch Exchange

BX

3

데이터 프로세싱

ADD, ADC, SUB, SBC, RSB, RSC, AND, ORR, BIC, MOV, MVN, CMP, CMN, TST, TEQ

4

곱셈

MUL, MLA, SMULL, SMLAL, SMULL, UMAL

5

Load/Store

LDR, LDRB, LDRBT, LDRH, LDRSB, LDRSH, LDRT, STR, STRB, STRBT, STRH, STRT

6

Load/Store 곱셈

LDM, STM

7

스왑

SWP, SWPB

8

SWI

SWI

9

PSR

MRS, MSR

10

코프로세서

MRC, MCR, LDC, STC, CDP

ARM에서 지원하는 7가지 동작모드

 

1. User 모드

태스크나 애플리케이션을 실행할 때의 동작모드이다.
비특권모드(Unprivileged)
메모리, I/O 장치와 같은 시스템 자원을 사용하는데 제한이 있다.

 

2. IRQ(Interrupt Request) 모드
인터럽트 요청에 대한 동작모드이다.
하 드웨어적인 외부장치의 요청에 의해 IRQ가 발생하면 IRQ 모드로 전환하고
인터럽트를 처리한다.

 

3. FIQ( Fast Interrupt Request) 모드
빠른 인터럽트 처리를 하는 모드이다.
하드웨어적인 외부장치의 요청에 FIQ가 발생하고 FIQ 모드로 전환하고
인터럽트를 처리한다.

 

4. SVC(Supervisor) 모드
대부분의 시스템 자원을 자유롭게 관리할 수 있는 동작모드이다.
운영체제의 커널이나 디바이스 드라이버를 처리할 때 사용되는 동작모드다.
ARM은 리셋신호가 입력되거나 소프트웨어 인터럽트(SWI)가 사용되면
SVC모드로 전환된다.

 

5. Abort 모드
메모리에서 명령을 읽거나 데이터를 읽고 쓸때 오류가 발생하면 Abort 모드로
전환하여 메모리 오류를 처리한다. MMU나 MPU, 기타 외부 메모리 제어기로부터
발생하는 Abort신호에서 동작한다.

 

6. Undefined 모드
명령어를 읽어 처리할 때 디코더에 정의되어 있지 않을 경우 발생하는 오류를
처리하기 위한 동작모드이다.

 

7. System 모드
특권(privilege) 모드라는 점을 제외하고는 User모드와 동일한 동작모드이다.

 


ARM은 User 모드와 System 모드는 소프트웨어적인 요청에 의해서만 전환이 되며
그외 다른 동작모드는 소프트웨어적인 요청이나 외부의 요청 혹은
오류에 의해 모드가 전환된다.

출처 : http://blog.naver.com/serimo/50091036891

U-Boot , 부트로더는 보통 NORNAND 플래시의 가장 앞부분 즉, 어드레스 0번지에 저장이 된다. ARM CPU에서 리셋이 걸리면 PC값이 0번지로 초기화되는데 이는 메모리맵에서

어드레스 0번지가 시작된다는 의미이다. 그러나 NOR 플래시와는 다르게 NAND플래시의 경우에는 읽기 동작시 블록단위로 동작을 하기 때문에 순차적인 실행 즉, 부팅 동작을 할 수 없다.

 

따라서 최신 CPU들은 이러한 NAND플래시 부팅을 지원하기 위해 별도의 기능들을 추가했다. 2410 CPU의 경우 리셋이 걸리면 DMA제어에 의해 4KB만큼 내부 SRAM으로 복사되고 SRAM의 시작 주소를 0번지로 할당하여 부팅동작을 하게한다. 하지만 U-Boot의 크기는 보통 160KB 정도 되는데 4KB를 훨씬 넘는 크기이다. 이러한 문제를 해결하기 위해 부트코드의 4KB 이내 코드의 동작은 아주 중요한 기본동작만 하고, 나머지는 시스템의 주메모리 즉, SDRAM에서 동작하게 PC(Program Count)의 위치를 SDRAM 메모리 영역으로 넘겨준다.

 

이렇게 하기 위해서 우선, 부트코드는 두 가지 방식으로 분리된다.

 

1.     시스템의 기본동작을 위한 초기화를 하고, NAND 플래시에 저장된 U-Boot의 전체 이미지를 SDRAM으로 복사한다. 이 동작은 간단하게 어셈블러 언어의 리터럴 풀(상수값 지정) 동작방식으로 메모리 접근이 가능하다.

 

2.     주메모리로 복사된 후 PC SDRAM으로 넘겨줄 때는 주로 복잡한 부팅기능을 지원하기 위해 C 프로그램으로 작성되어 실행이 되는데 이때는 자동변수를 위한 스택과 전역변수 그리고 다양한 라이브러리들이 링크될 수 있는 선형적인 메모리 접근이 용이하도록 절대주소방식을 사용한다.

 

따라서 메모리 용량이 작은 SRAM에서의 초기 부팅처리는 어셈블러로 코딩이 이루어져 있고 그 뒤 SDRAM으로 복사된 후의 복잡한 처리는 C프로그램으로 작성되어 있다.

 

어셈블러로 작성된 start.S의 코드는 CPU의 동작을 위해 비교적 간단하면서도 중요한 초기화 과정을 처리하고 있다. 먼저, CPU동작 모드를 유저모드에서 수퍼바이저(SVC32)모드로 전환하고 동작에 영향을 미칠 수 있는 인터럽트와 기타 하드웨어 기능을 중지하고 시스템 클럭을 설정한다. 또한 메모리 컨트롤러를 설정하고 NAND 플래시에 존재하는 부트코드를 SDRAM의 부트영역으로 복사하고 PC를 넘겨준다. C 프로그램의 실행을 위해 필요한 스택에 대한 설정이 이루어지고 나면 C로 구현된 부트로더의 시작함수를 호출한다.

출처 : http://blog.naver.com/serimo/50090962508

Cross Toolchains

We provide a set of apt-able tools built from standard Debian binutils and gcc sources.

We are currently working on keeping the tools synchronised with Debian, and maintaining installable sets for unstable, testing and lenny. Builds are still handled manually so are sometimes out of date. If you have any trouble finding current packages in the main repository, you may find something useful in Hector Oron's toolchain download area.
Please check Toolchain Wiki page for the latest news on the matter.

The cross-toolchains can not yet be built in Debian proper because there is no mechanism for the autobuilders to understand cross-dependencies. We are working on dealing with this problem so that crosstools can become standard debian packages, but until that is done you need to add the emdebian repository to your sources.list.
If you install emdebian-tools, and run emsetup -a arch it will add suitable sources.list entries for you. Be sure to edit /etc/apt/sources.list.d/ files and add your Debian suite.
To set things up manually edit /etc/apt/sources.list to add one of the lines below.

#
# -- Emdebian sources.list entries
#
# deb http://www.emdebian.org/debian/ unstable main
# deb http://www.emdebian.org/debian/ testing main
deb http://www.emdebian.org/debian/ lenny main

Then do apt-get update to update your local lists.

Once you have that then install whichever version of the tools you want. e.g:
apt-get install libc6-armel-cross libc6-dev-armel-cross binutils-arm-linux-gnueabi gcc-4.3-arm-linux-gnueabi g++-4.3-arm-linux-gnueabi
will install the gcc-4.3 C and C++ toolchain for armel cross-compiling.

For details on how to build your own tools see also how to build your own toolchain.

출처 : http://www.emdebian.org/

+ Recent posts