Microsoft PowerPoint - LN_4_Bootloader.ppt [호환 모드]

Similar documents
Microsoft PowerPoint - LN_2_Bootloader.ppt [호환 모드]

슬라이드 제목 없음

K&R2 Reference Manual 번역본

SRC PLUS 제어기 MANUAL

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202839C1D6C2F7207E203135C1D6C2F >

휠세미나3 ver0.4

hlogin2

GNU/Linux 1, GNU/Linux MS-DOS LOADLIN DOS-MBR LILO DOS-MBR LILO... 6

(Asynchronous Mode) ( 1, 5~8, 1~2) & (Parity) 1 ; * S erial Port (BIOS INT 14H) - 1 -

PowerPoint 프레젠테이션

Microsoft Word - FS_ZigBee_Manual_V1.3.docx

<4D F736F F F696E74202D20BBB7BBB7C7D15F FBEDFB0A3B1B3C0B05FC1A638C0CFC2F72E BC8A3C8AF20B8F0B5E55D>

Mango220 Android How to compile and Transfer image to Target

Here is a "PLDWorld.com"... // EXCALIBUR... // Additional Resources // µc/os-ii... Page 1 of 23 Additional Resources: µc/os-ii Author: Source: HiTEL D

KEY 디바이스 드라이버

Microsoft Word - 1. ARM Assembly 실습_xp2.doc

Microsoft PowerPoint - ch07.ppt

Solaris Express Developer Edition

MAX+plus II Getting Started - 무작정따라하기

(SW3704) Gingerbread Source Build & Working Guide

[8051] 강의자료.PDF

untitled

1217 WebTrafMon II

강의10

Mango-AM335x LCD Type 커널 Module Parameter에서 변경하기

PowerPoint 프레젠테이션

6주차.key

슬라이드 1

untitled

Deok9_Exploit Technique

Stage 2 First Phonics

INTRO Basic architecture of modern computers Basic and most used assembly instructions on x86 Installing an assembly compiler and RE tools Practice co

Poison null byte Excuse the ads! We need some help to keep our site up. List 1 Conditions 2 Exploit plan 2.1 chunksize(p)!= prev_size (next_chunk(p) 3

Microsoft PowerPoint - 03-Development-Environment-2.ppt

T100MD+

MPLAB C18 C

hd1300_k_v1r2_Final_.PDF

슬라이드 1

Remote UI Guide

목차 1. 제품 소개 특징 개요 Function table 기능 소개 Copy Compare Copy & Compare Erase

2. GCC Assembler와 AVR Assembler의차이 A. GCC Assembler 를사용하는경우 i. Assembly Language Program은.S Extension 을갖는다. ii. C Language Program은.c Extension 을갖는다.

CD-RW_Advanced.PDF

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202834C1D6C2F7207E2038C1D6C2F729>

Sena Technologies, Inc. HelloDevice Super 1.1.0

PowerPoint 프레젠테이션

DE1-SoC Board

PowerPoint 프레젠테이션

vi 사용법

Something that can be seen, touched or otherwise sensed

임베디드시스템설계강의자료 4 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

2 / 26

PowerPoint 프레젠테이션

MicrocontrollerAcademy_Lab_ST_040709

다음 사항을 꼭 확인하세요! 도움말 안내 - 본 도움말에는 iodd2511 조작방법 및 활용법이 적혀 있습니다. - 본 제품 사용 전에 안전을 위한 주의사항 을 반드시 숙지하십시오. - 문제가 발생하면 문제해결 을 참조하십시오. 중요한 Data 는 항상 백업 하십시오.

Chapter #01 Subject

R50_51_kor_ch1

Microsoft Word ARM_ver2_0a.docx

CPX-E-SYS_BES_C_ _ k1

PowerPoint 프레젠테이션

LCD Monitor

BMP 파일 처리

<32B1B3BDC32E687770>

CANTUS Evaluation Board Ap. Note

PowerChute Personal Edition v3.1.0 에이전트 사용 설명서

Chap06(Interprocess Communication).PDF

DSP_MON 프로그램 메뉴얼

CPX-E-EC_BES_C_ _ k1

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C D616E2E637070>

/chroot/lib/ /chroot/etc/

Microsoft Word doc

LCD Monitor

untitled

untitled

Microsoft PowerPoint - o8.pptx

API 매뉴얼

APOGEE Insight_KR_Base_3P11

본교재는수업용으로제작된게시물입니다. 영리목적으로사용할경우저작권법제 30 조항에의거법적처벌을받을수있습니다. [ 실습 ] 스위치장비초기화 1. NVRAM 에저장되어있는 'startup-config' 파일이있다면, 삭제를실시한다. SWx>enable SWx#erase sta

1. GigE Camera Interface를 위한 최소 PC 사양 CPU : Intel Core 2 Duo, 2.4GHz이상 RAM : 2GB 이상 LANcard : Intel PRO/1000xT 이상 VGA : PCI x 16, VRAM DDR2 RAM 256MB

Microsoft PowerPoint - 알고리즘_1주차_2차시.pptx

PowerPoint 프레젠테이션

Integ

Microsoft Word - ExecutionStack

Microsoft PowerPoint - polling.pptx

프로그램을 학교 등지에서 조금이라도 배운 사람들을 위한 프로그래밍 노트 입니다. 저 역시 그 사람들 중 하나 입니다. 중고등학교 시절 학교 도서관, 새로 생긴 시립 도서관 등을 다니며 책을 보 고 정리하며 어느정도 독학으르 공부하긴 했지만, 자주 안하다 보면 금방 잊어


API 매뉴얼

알아 둘 사항 아이오드 제조사는 본 기기에 하드디스크를 포함하여 출고하지 않습니다. 따라서 하드디스크에 문제가 발생할 경우, 구매처 또는 해당 하드디스크 서비 스센터에 문의 하시기 바랍니다. 정해진 용도 외의 사용으로 발생한 문제에 대해서, 당사는 어떠한 책임도 지지

Microsoft PowerPoint - 02-Development-Environment-1.ppt

Mango-E-Toi Board Developer Manual


10주차.key

슬라이드 제목 없음

H3050(aap)

10X56_NWG_KOR.indd

Microsoft PowerPoint - a10.ppt [호환 모드]

KDTÁ¾ÇÕ-1-07/03

Copyright 2004 Sun Microsystems, Inc Network Circle, Santa Clara, CA U.S.A..,,. Sun. Sun. Berkeley BSD. UNIX X/Open Company, Ltd.. Sun, Su

Transcription:

프로젝트 1 부트로더구조및원리파악 : Blob 소스분석 단국대학교컴퓨터학과 2009 백승재 ibanez1383@dankook.ac.kr k k http://embedded.dankook.ac.kr/~ibanez1383

Linux 의부팅과정이해 강의목표 실행파일과링커스크립트관계이해 부트로더구조및원리파악 Blob 을통한부트로더소스분석

Booting 의의미 Booting 의정의 Kernel이메모리에올려지고하드웨어가초기화되어바로사용가능한상태로만드는과정을부팅이라고한다. Booting 의목적 processor 초기화 memory 점검및초기화 각종하드웨어점검및초기화 kernel loading kernel 자료구조등록및초기화 사용환경조성

부팅과정도식도 (1/5) SUN Sparc, Intel ix86 ROM BIOS HDD 의 MBR Power On VGA 체크 Memory 체크 IDE 장치체크각종장치정보수집 FDD 의 MBR StrongARM, XScale, Flash Memory MBR 에있는 Boot loader 로딩또는 bootsect.s 로딩

부팅과정도식도 (2/5) kernel 을 main memory 로로딩 kernel 압축해제

부팅과정도식도 (3/5) 초기화 code 수행 start_kernel() { Architecture 의존적인설정 trap에대한초기화 } Interrupt에대한초기화 Scheduler 에대한초기화 softirq에대한초기화 Timer 초기화 Console 초기화 kernel module 사용을위한초기화 kernel cache 에대한초기설정 Clock tick과 BogoMIPS를구함 buddy system 사용을위한 memory 초기화 kernel cache 에대한초기화 fork에관한초기화 (max threads) 각종 kernel cache 및 buffer에대한생성및초기화 /proc 디렉토리에대한초기화 IPC 에대한초기화 SMP에대한초기화 init kernel thread 시작 kernel idle init kernel thread 각종 interface 장치초기화 network interface 초기화 initrd 로딩및 / mount free memory 재계산 console open /sbin/init process 수행

부팅과정도식도 (4/5) /sbin/init 수행 signal handler 설정 console 설정 /etc/inittab 파일 read /etc/rc.d/rc.sysinit script 수행 /etc/rc.d/rc script 수행 /sbin/mingetty 수행 run level 5이면 /etc/x11/prefdm수행 /etc/x11/prefdm /etc/rc.d/rc.sysinit host name 설정시간설정 usb 설정 file system check ISA 설정 sound 설정 /etc/rc.d/rc 3 run level에따른 /etc/rc*.d 디렉토리의 script 를수행 gdm 또는 kdm 또는 xdm 실행 /sbin/mingetty 가상터미널을띄우고 login 프로그램실행

부팅과정도식도 (5/5) /sbin/login 인증수행후 shell 실행 Shell 실행

MBR 의이해 (1/2) MBR 의이해 MBR이란하드디스크로부팅하기위한 boot loader와파티션분할정보, 부팅에사용되는실제파티션 (ACTIVE PARTITION) 에대한정보가저장된곳으로하드디스크의제일바깥쪽에위치한공간으로 ( 절대섹터 0(Cylinder 0, Head 0, Sector 1), 크기 :1sector(512byte)) 하드디스크로들어오는관문이되는곳이다. MBR은 boot sector에포함되나모든 boot sector가 MBR은아니다. boot sector는각파티션의첫번째 sector를의미한다. MBR 트랙0, 섹터1 플래터의구조

MBR 의이해 (2/2) MBR 이미지 (dd if=/dev/had of=mbr.img bs=1c count=512) LILO 문자열 time out 시간 jmp 0x7C second boot loader 의위치 map 파일 image 디스크립트 1 위치 Boot Loader code 파티션 1 파티션 2 파티션 3 파티션 4 fs type Magic number

Bootloader 의역할과종류 Boot Loader 의역할 Kernel을 memory에적재하고제어를 kernel로옮김 OS의선택적부팅 Kernel 다운로드를제공하기도한다 Embedded system을위한 boot loader는 BIOS에서해주는하드웨어초기화작업담당 Boot Loader 의종류 LILO 전통적인 linux boot loader이다. 일반적인 boot loader가그렇듯 assembly로짜여져있고크게 MBR에들어가는 first.s와 /boot/boot.b로만들어지는 second.s 두부분으로이루어져있다 GRUB 최근에주목받고있는 boot loader로서기능과유연성면에서 LILO보다앞선다. GNU에서만들었으며뛰어난 shell interface를제공한다 bootsector.s Kernel에서제공되는 boot loader로서압축된 kernel의제일앞 512byte 공간을차지하고있으며 floppy 등으로부팅할때사용되어지고다른 boot loader로부팅할때는건너띄는부분이다 Blob ARM SA-11x0 architecture 에서사용하는대표적인 boot loader 로서 GNU GPL 이여서사용에제한이없고 serial을통한다운로드를지원한다

프로젝트 1 Blob

~/src/start-ld-script Entry point 확인 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS {. = 0x00000000;. = ALIGN(4);.text : { *(.text) }. = ALIGN(4);.rodata : { *(.rodata) } 32bit ELF 포맷을가지는 little endian 형태의코드를생성 이파일이컴파일된뒤 ARM 이라는 Architecture에서실행됨을알려줌 실행파일의 entry point 가 _start 라는레이블임을알려줌 }. = ALIGN(4);.data : { *(.data) }. = ALIGN(4);.got : { *(.got) }. = ALIGN(4);.bss : { *(.bss) } 물리주소 0x00000000 번지에서수행이시작되며, 실행파일은코드가들어가있는 text와 rodata, data, got, bss의순서대로 4byte 단위로구성됨을의미

Memory 구성도 start.s 0x 0000 0000

_start 레이블 ~/src/start.s.text 영역의시작임을나타냄.text /* Jump vector table as in table 3.1 in [1] */.globl _start _start: b reset b undefined_instruction b software_interrupt b prefetch_abort b data_abort b not_used b irq.globl로선언된_start 즉, 외부에서 extern 해다쓸수있는 _start 심볼 b fiq ARM의각exception의 handler 를등록시켜놓은table

reset 레이블 ~/src/start.s IC_BASE:.word 0x90050000 #define ICMR 0x04 reset: /* First, mask **ALL** interrupts */ ldr r0, IC_BASE mov r1, #0x00 str r1, [r0, #ICMR] 모든인터럽트를불허함

~/src/start.s PWR_BASE:.word 0x90020000 #define PSPR 0x08 #define PPCR 0x14 reset 레이블 /* switch CPU to correct speed */ ldr r0, PWR_BASE LDR r1, cpuspeed str r1, [r0, #PPCR] /* setup memory */ bl memsetup /* init LED */ bl ledinit CPU clock speed 설정

reset 레이블 ~/src/start.s /* The initial CPU speed. Note that the SA11x0 CPUs can be safely overclocked: * 190 MHz CPUs are able to run at 221 MHz, 133 MHz CPUs can do 206 Mhz. */ #if (defined ASSABET) (defined CLART) (defined LART) (defined NESA) (defined NESA) cpuspeed:.long 00b 0x0b /* 221 MHz */ #elif defined SHANNON cpuspeed:.long 0x09 /* 191.7 MHz */ #else #warning "FIXME: Include code to use the correct clock speed for your board" cpuspeed:.long 0x05 /* safe 133 MHz speed */ #endif

~/src/memsetup.s memsetup 레이블.text MEM_BASE:.long 0xa0000000 MEM_START:.long 0xc0000000 #define MDCNFG 0x0 #define MDCAS0 0x04 #define MDCAS1 0x08 #define MDCAS2 0x0c #define MCS0 0x10 #if (defined BRUTUS) mdcas0:.long 0xc71c703f mdcas1:.long 0xffc71c71 mdcas2:.long 0xffffffff mdcnfg:.long 0x0334b22f mcs0:.long 0xfff8fff8 #endif.globl memsetup memsetup:

memsetup 레이블 ~/src/memsetup.s #elif defined USE_SA1110 /* This part is actually for the Assabet only. If your board MDCAS00, 20, 01, 21, 02, 22, MDREFR, MDCNFG register설정 * uses other settings, you'll have to ifdef f them here. */ /* Set up the SDRAM */ mov r1, #0xA0000000 /* MDCNFG base address */ ldr r2, =0xAAAAAA7F str r2, [r1, #0x04] /* MDCAS00 */ str r2, [r1, #0x20] /* MDCAS20 */ ldr r2, =0xAAAAAAAA str r2, [r1, #0x08] /* MDCAS01 */ str r2, [r1, #0x24] /* MDCAS21 */ ldr r2, =0xAAAAAAAA str r2, [r1, #0x0C] /* MDCAS02 */ str r2, [r1, #0x28] /* MDCAS22 */ ldr r2, =0x4dbc0327 /* MDREFR */ str r2, [r1, #0x1C] ldr r2, =0x72547254 /* MDCNFG */ str r2, [r1, #0x00]

~/src/memsetup.s memsetup 레이블 /* Issue read requests to disabled bank to start refresh */ disable 된뱅크에 refresh 가일어나는것을막기위해 8번반복하여읽기연산수행 ldr.rept 8 ldr.endr r1, =0xC0000000 r0, [r1] mov r1, #0xA0000000 /* MDCNFG base address */ ldr r2, =0x72547255 /* Enable the banks */ str r2, [r1, #0x00] /* MDCNFG */ 그런뒤 MDCNFG값을 0x72547255로설정하여 0/1 bank pair 활성화

memsetup 레이블 ~/src/memsetup.s /* Static memory chip selects on Assabet: */ ldr r2, =0x4b90 /* MCS0 */ orr r2,r2,r2,lsl #16 str r2, [r1, #0x10] ldr r2, =0x22212419 /* MCS1 */ str r2, [r1, #0x14] ldr r2, =0x42196669 /* MCS2 */ str r2, [r1, #0x2C] ldr r2, =0xafccafcc /* SMCNFG */ str r2, [r1, #0x30] /* Set up PCMCIA space */ ldr r2, =0x994a994a str r2, [r1, #0x18] /* All SDRAM memory settings should be ready to go... */ /* For best performance, should fill out remaining memory config regs: */ Board specific 한 PCMCIA/memory 설정을수행 gogogo2: /* Testing,Chester */ mov r3,#0x12000000 mov r2,#0x5000 /* D9_LED on and D8_LED off */ str r2,[r3] mov r4, #0x20000 subs r4, r4, #1 bne gogogo2 BL로점프해왔으므로lr값을 PC에복원하여원래위치로복귀 mov pc, lr

ledinit 레이블 ~/src/ledasm.s.text LED:.long LED_GPIO GPIO_BASE:.long 0x90040000 #define GPDR 0x00000004 #define GPSR 0x00000008 #define GPCR 0x0000000c LED 점등후원래루틴으로복귀.globl ledinit /* initialise LED GPIO and turn LED on. * clobbers r0 and r1 */ ledinit: ldr r0, GPIO_BASE ldr r1, LED str r1, [r0, #GPDR] /* LED GPIO is output */ str r1, [r0, #GPSR] /* turn LED on */ mov pc, lr

reset 레이블 ~/src/start.s RST_BASE:.word 0x90030000 #define RCSR 004 0x04 /* check if this is a wake-up from sleep */ ldr r0, RST_BASE ldr r1, [r0, #RCSR] and r1, r1, #0x0f teq r1, #0x08 bne normal_boot /* no, continue booting */ SA11X0엔 H/W reset, S/W reset, Watchdog reset, Sleep reset 네가지의 reset이존재한다. RCSR register는어떤이유로 reset 인터럽트가발생했는가를나타내며, RSSR register는 S/W reset을발생시키는 register이다. 따라서 Blob에선 RCSR register의값을읽어서하위네비트값을통해어떤이유로 reset되었는지를살펴본뒤, Sleep reset 인경우엔대응하는비트를클리어한뒤, PSPR register값을읽어 r1에넣어주고, 이값으로 jump함으로써이전상태로복원하게되며, 정상적인 H/W reset인경우라면 normal_boot 레이블로이동하게된다.

normal_boot 레이블 ~/src/start.s normal_boot: /* enable I-cache */ mrc p15, 0, r1, c1, c0, 0 @ read control reg orr r1, r1, #0x1000 @ set Icache mcr p15, 0, r1, c1, c0, 0 @ write it back I-cache enable 작업수행 control register 값을읽은뒤 Icache 를 set 하고 다시덮어씀

normal_boot 레이블 ~/src/start.s normal_boot: /* enable I-cache */ mrc p15, 0, r1, c1, c0, 0 @ read control reg orr r1, r1, #0x1000 @ set Icache mcr p15, 0, r1, c1, c0, 0 @ write it back I-cache enable 작업수행 control register 값을읽은뒤 Icache 를 set 하고 다시덮어씀 /* main memory starts at 0xc0000000 */ MEM_START:.long 0xc0000000 /* check the first 1MB in increments of 4k */ mov r7, #0x1000 mov r6, r7, lsl #8 /* 4k << 2^8 = 1MB */ ldr r5, MEM_START 메모리시작번지로부터 1MB를테스트한다. r7에 0x1000을넣고좌로 8번 shift연산을수행하여 r6에 1M를넣은후, 메모리의시작번지주소인 0xc000 0000 을 r5 register에넣는다.

normal_boot 레이블 ~/src/start.s mem_test_loop: mov r0, r5 bl testram teq r0, #1 beq badram add subs bne r5, r5, r7 r6, r6, r7 mem_test_loop 그런뒤 (~/src/testmem.s) 파일내에정의되어있는 testram 을호출하여메모리테스트수행

normal_boot 레이블 ~/src/start.s /* the first megabyte is OK, so let's clear it */ mov r0, #((1024 * 1024) / (8 * 4)) /* 1MB in steps of 32 bytes */ ldr r1, MEM_START mov r2, #0 mov r3, #0 mov r4, #0 mov r5, #0 mov r6, #0 mov r7, #0 mov r8, #0 mov r9, #0 clear_loop: stmia r1!, {r2-r9} subs r0, r0, #(8 * 4) bne clear_loop 이상없다면루프를돌면서확인된 1M영역의내용을 0으로초기화함. r0를 1MB/32 값을넣고, r1엔메모리의시작주소를넣는다. stmia 명령어를이용하여 r1이가리키는곳에r2-r9의값 (0) 을넣어주고r0의값을 32 만큼감소시킨다. 감소시킨값이 0이아니면계속하여루프를돌면서 1MB 영역을모두 0으로만든다

normal_boot 레이블 ~/src/start.s /* get a clue where we are running, so we know what to copy */ and r0, pc, #0xff000000 /* we don't care about the low bits */ /* relocate the second stage loader */ add r2, r0, #(128 * 1024) /* blob b is 128kB */ add r0, r0, #0x400 /* skip first 1024 bytes */ ldr r1, MEM_START add r1, r1, #0x400 /* skip over here as well */ Blob 자신을확인이완료된 RAM 으로복사하려한다. PC 값을이용해어디서부터복사해야하는지결정한다. Blob 의전체 size 가 128K 이므로복사작업을끝마쳐야하는주소즉, 현재 PC 에 128K 를더한값을 r2 에넣는다.

normal_boot 레이블 ~/src/start.s /* get a clue where we are running, so we know what to copy */ and r0, pc, #0xff000000 /* we don't care about the low bits */ /* relocate the second stage loader */ add r2, r0, #(128 * 1024) /* blob b is 128kB */ add r0, r0, #0x400 /* skip first 1024 bytes */ ldr r1, MEM_START add r1, r1, #0x400 /* skip over here as well */ r0에는 PC + 0x400 값을넣는다. r0는복사작업에서source의위치를나타내는데이는현재수행되고있는 start.s 외의다른파일의컴파일에관계가있는 rest-ld-script script 에.text 의시작이 0xc0000400 번지로지정되어있기때문이다. 다음으로 r1에는복사작업의 destination 값을넣어준다. 따라서복사작업에서 target 주소를나타내는 r1도 0xc0000400을가리키도록하여 rest-ld-script 로링킹된 binary 들이지장없이수행되도록한다.

normal_boot 레이블 ~/src/start.s copy_loop: ldmia r0!, {r3-r10} stmia r1!, {r3-r10} cmp r0, r2 ble copy_loop r0가가리키고있는곳의내용을r3~r10에담고이내용을r1이가리키고있는곳으로저장한다. 이작업은 source 의끝에해당되는 r2 와 ldmia 명령어를통해자동으로증가되고있는 r0값이같아질때까지수행된다. /* turn off the LED. if it stays off it is an indication that * we didn't make it into the C code */ bl led_off 디버그정보출력을위해 led 를끈다

normal_boot 레이블 ~/src/start.s /* set up the stack pointer */ ldr r0, MEM_START add r1, r0, #(1024 * 1024) sub sp, r1, #0x04 /* blob is copied to ram, so jump to it */ add r0, r0, #0x400 mov pc, r0 Stack pointer를 0xc0000000 + 1M 0x04 위치로설정한후 PC를방금복사해놓은RAM상의 Blob를가리키게한다. 따라서 0xc0000400 위치에있는실행파일로제어가넘어간다.

rest-ld-script OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_trampoline) SECTIONS {. = 0xc0000400; }. = ALIGN(4);.text : { *(.text) }. = ALIGN(4);.rodata : { *(.rodata) }. = ALIGN(4);.data : { *(.data) }. = ALIGN(4);.got : { *(.got) }. = ALIGN(4);.bss : { *(.bss) } 실행파일의 entry point가 _trampoline 이라는레이블임을알려줌물리주소 0xc0000400 번지에서수행이시작되며, 실행파일은코드가들어가있는text와 rodata, data,,g got, bss의순서대로 4byte 단위로구성됨을의미

Memory 구성도 start.s 0x 0000 0000 rest(trampoline.s, main.c ) 0x c000 0400

~/src/trampoline.s _trampoline 레이블.text t.globl _trampoline _trampoline: bl main /* if main ever returns we just call it again */ b _trampoline main 으로분기하는역할만을담당함 만약 main 에서리턴한다면다시분기

main 함수 ~/src/main.c int main(void) { u32 blocksize = 0x00800000; 00800000 int numread = 0; char commandline[128]; int i; int retval = 0; /* Turn the LED on again, so we can see that we safely made it * into C code. */ led_on(); /* We really want to be able to communicate, so initialise the * serial port at 9k6 (which works good for terminals) */ SerialInit(baud9k6); TimerInit(); S i li it(b d9k6) LED 를켠후, 시리얼포트를초기화한뒤 타이머를초기화하고, msg 출력 /* Print the required GPL string */ SerialOutputString(" nconsider yourself LARTed! n n"); SerialOutputString(PACKAGE " version " VERSION " n" "Copyright (C) 1999 2000 2001 " "Jan-Derk Bakker and Erik Mouw n" "Copyright (C) 2000 " "Johan Pouwelse n"); SerialOutputString(PACKAGE " comes with ABSOLUTELY NO WARRANTY; " "read the GNU GPL for details. n n"); SerialOutputString("This is free software, and you are welcome " "to redistribute it n"); SerialOutputString("under certain conditions; " "read the GNU GPL for details. n");

SerialInit() 함수 ~/src/serial.c void SerialInit(eBauds baudrate) { /* Theory of operations: * - Flush the output buffer * - switch receiver and transmitter off * - clear all sticky bits in control register 3 * - set the port to sensible defaults (no break, no interrupts, * no parity, 8 databits, 1 stopbit, transmitter and receiver * enabled * - set the baudrate to the requested value * - turn the receiver and transmitter back on */ #if defined USE_SERIAL1 while(ser1utsr1 & UTSR1_TBY) TBY) { } Ser1UTCR3 = 0x00; Ser1UTSR0 = 0xff; Ser1UTCR0 = ( UTCR0_1StpBit UTCR0_8BitData ); Ser1UTCR1 = 0; Ser1UTCR2 = (u32)baudrate; Ser1UTCR3 = ( UTCR3_RXE UTCR3_TXE ); #elif defined USE_SERIAL3 while(ser3utsr1 & UTSR1_TBY) { } Ser3UTCR3 = 0x00; Ser3UTSR0 = 0xff; Ser3UTCR0 = ( UTCR0_1StpBit UTCR0_8BitData ); Ser3UTCR1 = 0; Ser3UTCR2 = (u32)baudrate; Ser3UTCR3 = ( UTCR3_RXE UTCR3_TXE ); #else #error "Configuration error: No serial port used at all!" #endif }

TimerInit() 함수 ~/src/time.c void TimerInit(void) { /* clear counter */ OSCR = 0; /* we don't want to be interrupted */ 1개의 OSCR(Operating System Counter OIER = 0; Register)(up-counter register) 과 4개의 /* wait until OSCR > 0 */ OSMR(Operating System Match while(oscr == 0) Register) 존재 ; /* clear match register 0 */ OSMR0 = 0; /* clear match bit for OSMR0 */ OSSR = OSSR_M0; OSCR이 OSMR과일치되면 OSSR(Operating System Status Register) 의해당비트가set되고, INT가 enable된경우라면int발생됨 } numoverflows = 0;

main 함수 ~/src/main.c /* get the amount of memory */ get_memory_map(); /* initialise status */ blob_status.kernelsize = 0; blob_status.kerneltype = fromflash; blob_status.ramdisksize = 0; blob_status.ramdisktype = fromflash; blob_status.blocksize = blocksize; blob_status.downloadspeed = baud115k2; get_memory_map() 함수를호출하여시스템의메모리양을결정하고 blob_status 구조체에변수를초기화함

get_memory_map() 함수 ~/src/memory.c #define NUM_MEM_AREAS (32) typedef struct { u32 start; t; u32 len; int used; } memory_area_t; extern memory_area_t memory_map[num_mem_areas] /* memory start and end */ #define MEMORY_START (0xc0000000) #define MEMORY_END (0xe0000000) #define TEST_BLOCK_SIZE (1024 * 1024) void get_memory_map(void) { u32 addr; int i; /* init */ for(i = 0; i < NUM_MEM_AREAS; i++) memory_map[i].used = 0; /* first write a 0 to all memory locations */ for(addr = MEMORY_START; addr < MEMORY_END; addr += TEST_BLOCK_SIZE) * (u32 *)addr = 0; memory 의상태를저장할구조체의사용중을표시하는 used 필드를 clear 하고 실제물리메모리에 MegaB 단위로건너뛰면서 0 을쓴다

} get_memory_map() 함수 ~/src/memory.c i = 0; for(addr = MEMORY_START; addr < MEMORY_END; addr += TEST_BLOCK_SIZE) { if(testram(addr) == 0) { /* yes, memory */ if(* (u32 *)addr!= 0) { /* alias? */ } if(memory_map[i].used) map[i] i++; continue; /* not an alias, write the ~/src/testmem.s current address */ 내의 testram을호출하여메모리를검사한다. * (u32 *)addr = addr; /* does this start a new block? */ 정상적으로검사가수행되면 0을리턴한다. if(memory_map[i].used == 0) { memory_map[i].start = addr; memory_map[i].len = TEST_BLOCK_SIZE; memory_map[i].used map[i] = 1; } else { memory_map[i].len += TEST_BLOCK_SIZE; } } else { /* no memory here */ if(memory_map[i].used == 1) i++; } } SerialOutputString("Memory map: n"); for(i = 0; i < NUM_MEM_AREAS; i++) { if(memory_map[i].used) { SerialOutputString(" 0x"); SerialOutputHex(memory_map[i].len); SerialOutputString(" @ 0x"); SerialOutputHex(memory_map[i].start); } } 새로운 area 가아니라면이전 area 에 size 만더해준다. 새로운 area 라면구조체를적절히셋팅한다 SerialOutputString(" ("); SerialOutputDec(memory_map[i].len / (1024 * 1024)); SerialOutputString(" MB) n"); 그런뒤확인된메모리양을화면에출력

blob_status 구조체설명 typedef enum { fromflash = 0, fromdownload ownload = 1 } block_source_t; typedef struct { int kernelsize; block_source_t kerneltype; int ramdisksize; block_source_t ramdisktype; int blobsize; block_source_t blobtype; u32 blocksize; ebauds downloadspeed; } blob_status_t; 커널이미지의크기커널을어디서가져오는지를정의 Ramdisk 의크기 Ramdisk 를어디서가져오는지를정의 Blob 자체의크기 Blob를어디서가져오는지를정의 하나의 Block 의크기를정의 Downloading speed 를정의 blob_status_t blob_status;

main 함수 ~/src/main.c /* Load kernel and ramdisk from flash to RAM */ Reload("blob"); Reload("kernel"); Reload("ramdisk"); Reload() 함수를이용하여 blob, kernel, ramdisk 를메인메모리로끌고올라옴

~/src/main.cc void Reload(char *commandline) { u32 *src = 0; u32 *dst = 0; int numwords; if(mystrncmp(commandline, "blob", 4) == 0) { src = (u32 *)BLOB_RAM_BASE; dst = (u32 *)BLOB_START; numwords = BLOB_LEN / 4; blob_status.blobsize = 0; blob_status.blobtype = fromflash; SerialOutputString("Loading blob from flash "); } else if(mystrncmp(commandline, "kernel", 6) == 0) { src = (u32 *)KERNEL_RAM_BASE; dst = (u32 *)KERNEL_START; numwords = KERNEL_LEN / 4; blob_status.kernelsize = 0; blob_status.kerneltype = fromflash; SerialOutputString("Loading kernel from flash "); } else if(mystrncmp(commandline, "ramdisk", 7) == 0) { src = (u32 *)RAMDISK_RAM_BASE; dst = (u32 *)INITRD_START; numwords = INITRD_LEN / 4; blob_status.ramdisksize = 0; blob_status.ramdisktype = fromflash; SerialOutputString("Loading g ramdisk from flash "); } else { SerialOutputString("*** Don't know how to reload ""); SerialOutputString(commandline); SerialOutputString(" " n"); return; } Reload 함수 MyStrNCmp() 함수를이용하여인자로넘어온이미지를 Blob인경우0xc100 0000 번지에 Kernel인경우0xc000 8000 번지에 Ramdisk인경우0xc080 0000 번지에올린다. } MyMemCpy(src, dst, numwords); SerialOutputString(" done n");

Memory 구성도 start.s 0x 0000 0000 rest(trampoline.s, main.c ) 0x c000 0400 Kernel Ramdisk Blob 0x c000 8000 0x c080 0000 0x c100 0000

~/src/main.cc main 함수 /* wait 10 seconds before starting autoboot */ SerialOutputString("Autoboot in progress, press any key to stop "); for(i = 0; i < 10; i++) { SerialOutputByte('.'); 10초간기다린뒤별도의입력이없었다면리눅스를부팅시킨다 retval = SerialInputBlock(commandline, 1, 1); } if(retval > 0) break; /* no key was pressed, so proceed booting the kernel */ if(retval == 0) { commandline[0] = ' 0'; boot_linux(commandline); }

~/src/main.cc main 함수 void boot_linux(char *commandline) { register u32 i; void (*thekernel)(int zero, int arch) = (void (*)(int, int))kernel_ram_base; setup_start_tag(); setup_memory_tags(); setup_commandline_tag(commandline); setup_initrd_tag(); setup_ramdisk_tag(); tag(); setup_end_tag(); 커널이사용할 BOOT_PARAMS 를채워서메모리 0xc000 0100 에올려놓고 } /* we assume that the kernel is in place */ SerialOutputString(" nstarting kernel... n n"); /* turn off I-cache */ asm ("mrc p15, 0, %0, c1, c0, 0": "=r" (i)); i &= ~0x1000; asm ("mcr p15, 0, %0, c1, c0, 0": : "r" (i)); /* flush I-cache */ asm ("mcr p15, 0, %0, c7, c5, 0": : "r" (i)); thekernel(0, ARCH_NUMBER); SerialOutputString("Hey, the kernel returned! This should not happen. n"); I-cache 를끄고, flush 시킨뒤첫번째 arg에는 0을두번째 arg에는 ARCH_NUMBER를넣고제어를넘긴다.

tag구조체 linux/include/asm-arm/setup arm/setup.h struct tag_header { u32 size; u32 tag; }; struct tag { struct tag_header hdr; union { struct tag_core core; struct tag_mem32 mem; struct tag_videotext videotext; struct tag_ramdisk ramdisk; struct tag_initrd initrd; struct tag_serialnr serialnr; struct tag_revision revision; struct tag_videolfb videolfb; struct tag_cmdline cmdline; tag 의크기와 magic number 메모리의크기와시작주소비디오램의위치와 resolution ramdisk의옵션, 크기및시작주소 Initial RAM disk의크기와시작주소 Serial의개수 Revision 번호 Video Frame Buffer의설정사항 }; } u; /* * Acorn specific */ struct tag_acorn acorn; /* * DC21285 specific */ struct tag_memclk memclk;

Memory 구성도 start.s 0x 0000 0000 BOOT_PARAMS rest(trampoline.s, main.c ) 0x c000 0100 0x c000 0400 Kernel Ramdisk Blob 0x c000 8000 0x c080 0000 0x c100 0000