부트 로더 (blob-2.0.5-pre2 중심 )

32
부부 부부 (blob-2.0.5-pre2 부 부) Lecture #8 Lecture #8

Upload: meli

Post on 14-Jan-2016

49 views

Category:

Documents


0 download

DESCRIPTION

부트 로더 (blob-2.0.5-pre2 중심 ). Lecture #8. 목 차. BLOB 소개 주요 명령 BLOB 컴파일 방법 이미지 파일 복사 경로 BLOB 메모리 맵 BLOB 구조 Makefile 및 로드 스크립트 start 부분 jump 벡터 (start.S) / 예외 처리 (start.S) rest 부분 bss 및 stack 설정 (trampoline.S) / 함수 main (main.c) - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 부트 로더  (blob-2.0.5-pre2  중심 )

부트 로더 (blob-2.0.5-pre2 중심 )

Lecture #8Lecture #8

Page 2: 부트 로더  (blob-2.0.5-pre2  중심 )

2

목 차 BLOB 소개 주요 명령 BLOB 컴파일 방법 이미지 파일 복사 경로 BLOB 메모리 맵 BLOB 구조 Makefile 및 로드 스크립트 start 부분

jump 벡터 (start.S) / 예외 처리 (start.S) rest 부분

bss 및 stack 설정 (trampoline.S) / 함수 main (main.c) 주요 명령 처리 함수 : reboot, boot_linux, Flash, do_reload, reblob

Page 3: 부트 로더  (blob-2.0.5-pre2  중심 )

3

BLOB 소개 네덜란드의 Delft University of Technology 에서 개발 LART(Linux Advanced Radio Terminal) 라는 리눅스

기반 공개 소스 내장형 컴퓨터 ( 인텔 SA-1100 마이크로 프로세서 사용 ) 에 사용된 부트 로더

현재 blob-2.0.5-pre2 가 가장 최근 버전임 URL: http://www.lart.tudelft.nl/lartware/blob

Page 4: 부트 로더  (blob-2.0.5-pre2  중심 )

4

주요 명령 reset: 직렬 포트에 화면을 clear 하는 문자 (ESC-c) 를 보냄 reboot: 0x00000000 로 제어를 옮김 (=power on reset) boot: SDRAM 의 kernel 이 저장된 지점으로 제어를 옮김 download: 호스트에서 키트의 SDRAM 으로 이미지 파일 복사 (uuencode

사용 ) xdownload: 호스트에서 키트의 SDRAM 으로 이미지 파일 복사 (xmodem

사용 ) flash: SDRAM 에 있는 이미지 파일을 flash 메모리로 저장함 erase: flash 메모리의 특정 부분을 지움 speed: 키트의 직렬 포트의 baud rate 을 변경 status: 버전 , flash 메모리 상태 , IP 주소 , MAC 주소 등을 보여줌 reload: flash 메모리에 저장된 이미지를 SDRAM 으로 복사 tftp: 서버로 부터 tftp 를 사용하여 이미지 파일을 SDRAM 으로 복사 set: IP 주소 및 MAC 주소를 설정 reblob: 0xa0300000 으로 제어를 옮김 (=SDRAM 에 복사된 BLOB 수행 ) btp: BOOTP 서버로 부터 키트의 IP 주소를 받아옴 help: 도움말 출력

Page 5: 부트 로더  (blob-2.0.5-pre2  중심 )

5

BLOB 컴파일 방법 리눅스 kernel 소스 트리 필요

"/home/et1/linux-2.4.19-pxa255_pro2" 에 만들어져 있다고 가정

BLOB 를 configure 한다$ sh configure --with-linux-prefix= /home/et1/linux-2.4.19-pxa

255_pro2 --with-board=pxa255_pro BLOB 를 make 한다

$ make( 주 : 파일 src/blob/blob 가 새로 만들어진 이미지임 )

Page 6: 부트 로더  (blob-2.0.5-pre2  중심 )

6

이미지 파일 복사 경로 download {blob|param|kernel|ramdisk|root|

usr} 호스트 컴퓨터 -> SDRAM

flash {blob|param|kernel|ramdisk|root|usr} SDRAM -> flash 메모리

reload {blob|param|kernel|ramdisk} flash 메모리 -> SDRAM

Page 7: 부트 로더  (blob-2.0.5-pre2  중심 )

7

BLOB 메모리 맵

Page 8: 부트 로더  (blob-2.0.5-pre2  중심 )

8

boot_linux

run command

boot_linux () SetClock () Download() Flash() ......

Auto Boot Manual Boot

GetCommand ()

start.S

점프

명령어 모드

하드웨어초기화

시리얼 초기화

커널 , 램디스크를 램에 복사10초간가다린후실행 키가 10초안에누렸을때

main()

() () SetClock Download() Flash() ......

GetCommand ()

커널로

명령어 모드

메모리초기화

타임머 초기화

10 키가 10초안에누렸을때

BLOB 실행 흐름

Page 9: 부트 로더  (blob-2.0.5-pre2  중심 )

9

BLOB 구조 BLOB 는 2 부분으로 나누어져 있다

start 부분 : flash 메모리 상에서 수행되는 부분 reset 부분 : flash 메모리에서 SDRAM 으로 복사된 후

SDRAM 상에서 수행되는 부분 BLOB 의 프로그램이 모두 flash 메모리에서 수행되지

않고 reset 부분이 SDRAM 으로 복사되어 SDRAM 상에서 수행되는 이유 flash 메모리 상에서 수행되면서 flash 명령을 수행할 수 없기

때문임 SDRAM 에서 수행하는 것이 flash 메모리에서 수행하는 것

보다 더 효율적임

Page 10: 부트 로더  (blob-2.0.5-pre2  중심 )

10

start 부분 flash 메모리 0x00000000 번지부터 저장 start.S 파일에서 수행 시작됨 프로그램은 ARM 어셈블리 언어로 작성 하는 일

하드웨어 초기화 작업을 수행 Xscale, GPIO, SDRAM 등 초기화

BLOB 의 reset 부분을 SDRAM 에 있는 0xa0400400 번지(=BLOB_START) 로 복사

BLOB_START(rest 부분 ) 로 jump

Page 11: 부트 로더  (blob-2.0.5-pre2  중심 )

11

rest 부분 flash 메모리 0x00000400 번지부터 저장 ( 주 : 저장만

여기에 되어있지 실제는 0xa0400400 번지에 로드되어 수행된다는 가정하에 링크되어 )

flash 메모리 상에서 수행되지 않고 SDRAM 을 복사되어 SDRAM 상에서 수행

trampoline.S 파일에서 수행이 시작되자마자 main.c 파일의 함수 main() 을 부름

프로그램은 C 언어로 작성되어 있음 BLOB 의 대부분의 기능을 수행

blob, kernel, ramdisk 를 flash 메모리에서 SDRAM 으로 복사 이더넷 초기화 직렬 포트에서 입력이 없으면 SDRAM 의 kernel 부분으로 jump

하고 그렇지 않으면 명령어 모드로 수행

Page 12: 부트 로더  (blob-2.0.5-pre2  중심 )

12

Makefile - 1

blob_start_elf32_OBJECTS = start.o testmem.oblob_start_elf32_DEPENDENCIES = start-ld-scriptblob_rest_elf32_OBJECTS = trampoline.o flashasm.o stack.o testmem2.o \

bootldrpart.o commands.o flash.o initcalls.o linux.o main.o memory.o \param_block.o partition.o reboot.o uucodec.o scc.o net.o bootp.o tftp.o \xmodem.o

blob_start_elf32_DEPENDENCIES = rest-ld-script

blob-start-elf32: $(blob_start_elf32_OBJECTS) $(blob_start_elf32_DEPENDENCIES)$(LINK) $(blob_start_elf32_LDFLAGS) $(blob_start_elf32_OBJECTS) \

$(blob_start_elf32_LDADD) $(LIBS)

blob-rest-elf32: $(blob_rest_elf32_OBJECTS) $(blob_rest_elf32_DEPENDENCIES)$(LINK) $(blob_rest_elf32_LDFLAGS) $(blob_rest_elf32_OBJECTS) \

$(blob_rest_elf32_LDADD) $(LIBS)

Page 13: 부트 로더  (blob-2.0.5-pre2  중심 )

13

Makefile - 2

OBJCOPY = arm-linux-objcopyOCFLAGS = -O binary -R .note -R .comment -S

blob: blob-start blob-rest dd if=blob-start of=$@ bs=1k conv=sync dd if=blob-rest of=$@ bs=1k seek=1 chmod +x $@

blob-start: blob-start-elf32 $(OBJCOPY) $(OCFLAGS) $< $@

blob-rest: blob-rest-elf32 $(OBJCOPY) $(OCFLAGS) $< $@

Page 14: 부트 로더  (blob-2.0.5-pre2  중심 )

14

BLOB-start

(1Kbyte)

BLOB-rest

(63Kbyte)

BLOB

trampoline.o

flashasm.o stack.o

testmem2.o

bootldrpart.o

commands.o flash.o

initcalls.o linux.o

main.o memory.o

param_block.o

partition.o reboot.o

uucodec.o

scc.o net.o

bootp.o tftp.o

xmodem.o

start.o

testmem.o

BLOB 소스 구조

Page 15: 부트 로더  (blob-2.0.5-pre2  중심 )

15

"start 부분 " 로드 스크립트ENTRY(_start)SECTIONS{ . = 0x00000000; // location counter = 0x00000000

. = ALIGN(4); // align 4 를 함 .text : { *(.text) } // 모든 text 를 여기에 모음

. = ALIGN(4); // align 4 를 함 .rodata : { *(.rodata) } // 모든 read only 데이터 모음

. = ALIGN(4); // align 4 를 함 .data : { *(.data) } // 모든 초기화된 데이터 모음

. = ALIGN(4); // align 4 를 함 .got : { *(.got) } // 모든 global offset table 을 모음

. = ALIGN(4); // align 4 를 함 .bss : { *(.bss) } // 모든 초기화 되지 않은 데이터 모음}

Page 16: 부트 로더  (blob-2.0.5-pre2  중심 )

16

"rest 부분 " 로드 스크립트SECTIONS{ . = (0xa0400400); // location counter = 0xa0400400

. = ALIGN(4); // align 4 를 함 .text : { __text_start = .; // __text_start = 현재 location counter *(.text) // 모든 text 를 여기에 모음 __text_end = .; // __text_end = 현재 location counter } ...}

Page 17: 부트 로더  (blob-2.0.5-pre2  중심 )

17

최종 blob 이미지 모습

"start 부분 " 에서 "rest 부분 " 으로 수행이 넘어가기 전에 flash 메모리의 1K ~ 64K 의 내용을 SDRAM 의 0xa0400400 에 복사한다

blob-start blob-restnull

0 1K

???

64Kblob 끝

Page 18: 부트 로더  (blob-2.0.5-pre2  중심 )

18

jump 벡터 (start.S)

ARM 의 7 가지 예외 발생시 수행하여야 하는 명령어가 저장된 곳 메모리 0x00000000 번지 (flash 메모리 부분 ) 부터 32 바이트 저장됨 저장된 명령어는 예외 처리 루틴의 첫 주소로 jump 하는 명령어임

_start:b reset // resetb undefined_instruction // undefined instructionb software_interrupt // software interrupt (swi)b prefetch_abort // instruction fetch memory abortb data_abort // data access memory abortb not_used // not usedb irq // interruptb fiq // fast interrupt

Page 19: 부트 로더  (blob-2.0.5-pre2  중심 )

19

reset 예외 처리 (start.S)

reset:bl init_xscalebl init_gpiobl init_mem...

relocate:// BLOB reset 부분 relocateadr r0, _startadd r2, r0, #(64*1024)add r0, r0, #0x0400ldr r1, BLOB_START

// r0 = source address// r1 = target address// r2 = source end addresscopy_loop:

ldmia r0!, {r3-r10}stmia r1!, {r3-r10}cmp r0, r2ble copy_loop

ldr r0, BLOB_STARTmov pc, r0

reset 예외는 init_xscale, init_gpio, init_mem 을 부르고 flash 메모리에 저장된 BLOB 의 "rest 부분 " 을 SDRAM 의

BLOB_START(=0xa0400400) 로 복사하고 이곳으로 jump

Page 20: 부트 로더  (blob-2.0.5-pre2  중심 )

20

기타 예외 처리 (start.S)

undefined_instruction:b endless_blink

software_interrupt:b endless_blink

...

riq:b endless_blink

fiq:b endless_blink

endless_blink:bl waitbl flash_ledb endless_blink

wait: // busy wait loopmov r5, #0x1000000

wait0:subs r5, r5, #1bne wait0mov pc, lr

"reset 예외 " 를 제외한 다른 예외는 모두 endless_blink 로 jump 함 endless_blink 로 가면 LED 를 계속 깜박거리게 함

Page 21: 부트 로더  (blob-2.0.5-pre2  중심 )

21

bss 및 stack 설정 (trampoline.S)

_trampoline:ldr r1, bss_startldr r0, bss_endsub r0, r0, r1mov r2, #0

// r0 = bss 바이트 수// r1 = bss start 주소// r2 = 0

clear_bss:// bss 부분을 clearstmia r1!, {r2}subs r0, r0, #4bne clear_bss// 스택 설정ldr r0, stack_endsub sp, r0, #4// C 코드 함수 main() call bl main

r0=bss 바이트 수 , r1=bss 시작 주소 , r2=0 을 설정한 후 , SDRAM 의 bss 영역을 r2 로 채우고 , SP=stack_end-4 로 설정하고 C 코드로 작성된 파일 main.c 에 정의된 함수 main 을 call

Page 22: 부트 로더  (blob-2.0.5-pre2  중심 )

22

함수 main (main.c) - 1

int main(void){ ... serial_init(blob_status.terminalSpeed); ... SerialOutputString("\nConsider yourself LARTed!\n\n"); ... get_memory_map(); print_elf_sections(); EthInit(); ... do_reload("blob"); do_reload("kernel"); do_reload("ramdisk"); ...

직렬 포트 초기화 , 메시지 출력 , 메모리 크기 점검 , elf section 출력 , 이더넷 초기화 등의 일을 하고

blob, kernel, ramdisk 이미지를 flash 메모리에서 SDRAM 으로 복사

Page 23: 부트 로더  (blob-2.0.5-pre2  중심 )

23

함수 main (main.c) - 2

SerialOutputString("Autoboot in progress, press any key to stop");

for(i = 0; i < blob_status.boot_delay; i++) // 키 입력 점검

if((retval=SerialInputBlock(commandline, ...)>0) break

if(retval == 0) parse_command("boot"); // 키 입력 없음

SerialOutputString("\nAutoboot aborted\n"); // 키 입력 있음

for(;;)

GetCommand(commandline, ...);

}

지정된 delay 동안 키 입력이 있는지 점검하고 키이 입력이 없으면 boot 를 불러서 SDRAM 의 kernel 번지로 jump 키이 입력이 있으면 함수 GetCommand 를 불러서 명령어 입력 받음

Page 24: 부트 로더  (blob-2.0.5-pre2  중심 )

24

주요 명령 처리 함수

명령 reboot -> 함수 reboot (reboot.c)

명령 boot -> 함수 boot_linux (linux.c)

명령 flash -> 함수 Flash, flash_write_region (flash.c)

명령 reload -> 함수 do_reload (main.c)

명령 reblob -> 함수 reblob (reboot.c)

Page 25: 부트 로더  (blob-2.0.5-pre2  중심 )

25

함수 reboot (reboot.c)

int reboot(int argc, char *argv[])

{

void (*Reboot)(void) = (void (*)(void))0x00000000;

SerialOutputString("Rebooting...\n\n");

Reboot();

}

함수 void Reboot(void) 를 flash 메모리의 0x00000000 번지로 정의하고 이 함수를 call 한다

power on reset 과 같은 효과가 있음

Page 26: 부트 로더  (blob-2.0.5-pre2  중심 )

26

함수 boot_linux (linux.c)

static int boot_linux(int argc, char *argv[]) { void (*theKernel)(int zero, int arch)=(void(*)(int,int)) KERNEL_RAM_BASE;

SerialOutputString("\nStarting kernel ...\n\n"); theKernel(0, ARCH_NUMBER);}

함수 void theKernel(int,int) 를 SDRAM 의 KERNEL_RAM_BASE (=0xa0008000) 번지로 정의하고 이 함수를 call 한다 ( 인수는 0 과 ARCH_NUMBER=110)

Page 27: 부트 로더  (blob-2.0.5-pre2  중심 )

27

함수 Flash (main.c)

static int Flash(int argc, char *argv[]) { u32 *src, *dst; u32 numBytes;

if(strncmp(argv[1], "blob", 5) == 0) { src = (u32 *)BLOB_RAM_BASE; dst = (u32 *)BLOB_FLASH_BASE; numBytes = blob_status.blobSize;}

argv[1] 의 값에 따라 blob, kernel, ramdisk, usr 등으로 인식하고 이에 따라 src, dst, numByte 를 결정한다

함수 flash_write_region 을 부른다

else if ... { ... }

nwords = (numBytes + sizeof(u32) - 1) / sizeof(u32);

flash_write_region(dst, src, nwords);}

Page 28: 부트 로더  (blob-2.0.5-pre2  중심 )

28

함수 flash_write_region (flash.c)

int flash_write_region(u32 *dst, const u32 *src, u32 nwords)

{ int rv; u32 i = 0;

while(i < nwords) { if(dst[i] == src[i]) { i++; continue; }

SDRAM 의 주소 (=src) 에서 nword 만큼의 데이터를 flash 메모리의 주소 (=dst) 에 write 한다 . 함수 flash_write_intel32 를 부름

rv = flash_write_intel32(&dst[i], &src[i]); ... }}

Page 29: 부트 로더  (blob-2.0.5-pre2  중심 )

29

Intel flash 메모리 (16bit 칩 *2) write 방법

PGM_SETUP(=0x00400040): 이 명령을 flash 메모리 ( 어떤 번지나 무방 ) 에 쓰면 flash 메모리가 write 될 준비를 한다

write 할 번지에 원하는 데이터를 쓴다 (*dst = *src; )

STATUS_READ(=0x00700070): 이 명령을 flash 메모리 ( 어떤 번지나 무방 ) 에 쓴 후 flash 메모리 ( 어떤 번지나 무방 ) 의 내용을 읽으면 현재 flash 메모리의 상태가 읽혀진다 . 현재 BLOB 에서 write 후 점검하는 상태는 STATUS_BUSY(=0x00800080) 및 STATUS_PGM_ ERR(=0x00100010) 이다

READ_ARRAY(=0x00ff00ff): 이 명령을 flash 메모리에 ( 어떤 번지나 무방함 ) 쓰면 flash 메모리가 read 할 수 있는 상태로 된다 . write 완료 후 필요한 명령임

Page 30: 부트 로더  (blob-2.0.5-pre2  중심 )

30

함수 flash_write_intel32 (flash.c)

static int flash_write_intel32(u32 *dst, const u32* src){ *dst = data_to_flash(PGM_SETUP); // 쓰기 준비 *dst = *src; // 데이터 쓰기 do { *dst = data_to_flash(STATUS_READ); // 상태 읽기 준비 result = data_from_flash(*dst); // 상태 읽기 } while((~result & STATUS_BUSY) != 0); // 상태 점검 (STATUS_BUSY) *dst = data_to_flash(READ_ARRAY); // 정상 상태 (= 읽기 모드 ) 로 설정}

PGM_SETUP(=0x00400040), STATUS_READ(=0x00700070), READ_ARRAY(=0x00ff00ff) 명령을 사용하여 원하는 flash 메모리에 데이터를 write 한다

Page 31: 부트 로더  (blob-2.0.5-pre2  중심 )

31

함수 do_reload (main.c)

static int do_reload(char *what) { u32 *dst = 0; *src = 0; int numWords;

if(strncmp(what, "blob", 5) == 0) { dst = (u32 *)BLOB_RAM_BASE; src = (u32 *)BLOB_FLASH_BASE; numWords = BLOB_FLASH_LEN / 4; SerialOutputString("Loading blob from flash "); } else if ... MyMemCpy(dst, src, numWords);}

what 이 무엇이냐에 따라 flash 메모리의 주소 , SDRAM 의 주소 , flash 메모리에서의 크기를 설정하고 함수 MyMemCpy 를 call 한다

함수 MyMemCpy 는 flash 메모리의 이미지를 SDRAM 으로 복사한다

Page 32: 부트 로더  (blob-2.0.5-pre2  중심 )

32

함수 reblob (reboot.c)

static int reblob(int argc, char *argv[]){ void (*blob)(void) = (void (*)(void))BLOB_RAM_BASE;

SerialOutputString("Restarting blob from RAM...\n\n"); blob();}

함수 void blob(void) 를 SDRAM 의 BLOB_RAM_BASE (=0xa0300000) 번지로 정의하고 이 함수를 call 한다

SDRAM 의 BLOB_RAM_BASE 에 복사된 BLOB 가 수행 가능한 이유는 "start 부분 " 이 어셈블리 언어로 작성되어 있고 주소가 현재 PC 값에 대한 상대적인 값으로 지정되어 있기 때문