부트 로더 (blob-2.0.5-pre2 중심) Lecture #8.

Slides:



Advertisements
Similar presentations
(실습) 부트로더 [BootLoader]
Advertisements

ISA 심화 및 start.S code 분석 SIOR 15th 최재훈.
Linux Debugging issues
Basic of Buffer Over Flow
ROBOTICS LAB. DSP TMS320F2812 ROBOTICS LAB.
9. 부트로더 분석.
Linux/UNIX Programming APUE (The Environment of a UNIX Process)
Power C++ 제6장 포인터와 문자열.
제3장 C 프로그래밍 환경.
U-boot(Universal Bootloader)
제 2장 컴퓨터 구조.
프로그램 제어 분기(branch)와 점프(jump) 명령어 PC의 값의 변경 순차적인 프로그램의 진행순서가
부트로더 Blob.
기본 컴퓨터 프로그래밍 Lecture #6.
C 프로그래밍 소개 숙명여대 창병모 2011 가을.
Windows CE 시스템 개발 환경 구축.
제6장 FUSING.
제 1 장 마이크로프로세서의 기본동작.
CPU의 이해 CPU란 무엇인가?
V44408(다산네트웍스) 개량개선 내역(1.05) KT 네트워크기술지원본부 유선액세스망기술담당 1
3장. 라우터와 스위치의 기본설정 2012년 2학기 중부대학교 정보보호학과 이병천 교수.
3장 MPU 내부구조 Slide 1 (of 28).
임베디드 하드웨어 Lecture #6.
FUSING.
Department of Computer Engineering
제9장 C 프로그래밍 환경 창병모
목차 커널의 개념 및 기능 커널 포팅 램디스크.
Development Environment of Embedded System : part 1
MicroC/OS-II Lab. 경희대학교 컴퓨터공학과 조 진 성.
출처: IT CookBook, 컴퓨터 구조와 원리 2.0 제 12장
PowerPC ABI 김종화.
3COM 스위치 교육 자료.
전원설비 포인트연결어댑터 교육자료 주식회사 필 트 론.
컴퓨터 구조.
4장. 컴퓨터 시스템의 구성과 기능 다루는 내용 컴퓨터 분해를 통한 본체 살펴보기 컴퓨터 구성요소 컴퓨터의 기능
임베디드 시스템 개론 3주차 Embedded System..
버퍼 오버플로우 시스템보안 인터넷공학전공 권영락.
Embedded System Porting (2)
Department of Computer Engineering
9장. 중앙처리 장치의 조직과 기능 다루는 내용 컴퓨터 본체에서 CPU의 위치 살펴보기 CPU의 성능, 기능, 조직
3장. 라우터와 스위치의 기본설정 2012년 2학기 중부대학교 정보보호학과 이병천 교수.
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express.
Term Project Team Member
ARM 명령어 집합 Lecture #7.
부트 로더 (blob pre2 중심) Lecture #8.
Geek-OS Project 정영진
3주 컴퓨터구조.
UniSQL/X 실습과제 (1) ■ 실습 기간: ~
BOF of 2.6 Kernel ! 박수완 / Su-Wan, PARK [ L1nkC] 숭실대학교 정보보호동아리 ACK
Host PC & Target Board 환경설정 Embedded Linux Image 올리기
임베디드 소프트웨어 설계.
10장. 중앙처리 장치의 명령어 다루는 내용 어셈블리 프로그램의 이해 인터럽트(interrupt) 명령어 세트 주소 지정 방식.
Boot Loader.
Chapter 4 The Von Neumann Model.
Computer System Architecture
9. 부트로더 분석.
cafe.naver.com/embeddedcrazyboys
ARM Development Suite v1.2
8051 IO-PORT 정보통신•컴퓨터 공학부 송명규
Stepper Motor 디바이스 드라이버
9장. 중앙처리 장치의 조직과 기능 다루는 내용 컴퓨터 본체에서 CPU의 위치 살펴보기 CPU의 성능, 기능, 조직
Department of Computer Engineering
ARM Development Suite v1.2
자료구조 세미나 발표 주제: 자료구조 기초 - 1회 차: 자료구조의 정의, 기초 지식 (함수, 포인터, 레퍼런스)
9장. C 언어의 핵심! 함수. 9장. C 언어의 핵심! 함수 9-1 함수의 정의와 선언 main 함수 다시 보기 : 함수의 기본 형태 { } 그림 9-1.
ARM Development Suite v1.2
10장. 컴퓨터 구조에 대한 세 번째 이야기 작성자: 윤성우.
임베디드 하드웨어 Lecture #6.
Lecture 7 7-Segment LED controller using u-controller
ARM Development Suite v1.2
Presentation transcript:

부트 로더 (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) 주요 명령 처리 함수: reboot, boot_linux, Flash, do_reload, reblob

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

주요 명령 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: 도움말 출력

BLOB 컴파일 방법 리눅스 kernel 소스 트리 필요 BLOB를 configure한다 BLOB를 make한다 "/home/et1/linux-2.4.19-pxa255_pro2"에 만들어져 있다고 가정 BLOB를 configure한다 $ sh configure --with-linux-prefix= /home/et1/linux-2.4.19-pxa255_pro2 --with-board=pxa255_pro BLOB를 make한다 $ make (주: 파일 src/blob/blob가 새로 만들어진 이미지임)

이미지 파일 복사 경로 download {blob|param|kernel|ramdisk|root|usr} 호스트 컴퓨터 -> SDRAM flash {blob|param|kernel|ramdisk|root|usr} SDRAM -> flash 메모리 reload {blob|param|kernel|ramdisk} flash 메모리 -> SDRAM

BLOB 메모리 맵

BLOB 실행 흐름 boot_linux run command () SetClock Download() Flash() ...... Auto Boot Manual Boot GetCommand start.S 점프 명령어 모드 하드웨어초기화 시리얼 초기화 커널,램디스크를 램에 복사 10 초간 가다린후 실행 키가 초안에 누렸을때 main() 커널로 메모리초기화 타임머 초기화 Blob는 어셈블러 코드인 start.S에서 시작한다. 이곳에서는 기본적인 하드웨어 초기화를 수행한 후 C 코드를 수행하기 위해 stack pointer를 설정하고 main.c의 c_main() 함수로 제어를 넘긴다. c_main()에서는 serial device와 timer를 초기화 한 후 커널과 램디스크 이미지를 램에 복사하면서 10초간 사용자의 입력을 기다린다.(현재 소스에는 1초로 되어있다.) 사용자가 아무런 입력도 하지 않으면 BootKernel() 함수를 수행하여 kernel로 제어를 넘기게 되고 사용자에게 입력(any key) 을 받으면 kernel로 부팅하지 않고 사용자에게 명령을 받을 준비를 하고 기다리게 된다.

BLOB 구조 BLOB는 2부분으로 나누어져 있다 start 부분: flash 메모리 상에서 수행되는 부분 reset 부분: flash 메모리에서 SDRAM으로 복사된 후 SDRAM 상에서 수행되는 부분 BLOB의 프로그램이 모두 flash 메모리에서 수행되지 않고 reset 부분이 SDRAM으로 복사되어 SDRAM 상에서 수행되는 이유 flash 메모리 상에서 수행되면서 flash 명령을 수행할 수 없기 때문임 SDRAM에서 수행하는 것이 flash 메모리에서 수행하는 것 보다 더 효율적임

start 부분 flash 메모리 0x00000000 번지부터 저장 start.S 파일에서 수행 시작됨 프로그램은 ARM 어셈블리 언어로 작성 하는 일 하드웨어 초기화 작업을 수행 Xscale, GPIO, SDRAM 등 초기화 BLOB의 reset 부분을 SDRAM에 있는 0xa0400400 번지(=BLOB_START)로 복사 BLOB_START(rest 부분)로 jump

rest 부분 flash 메모리 0x00000400 번지부터 저장 (주: 저장만 여기에 되어있지 실제는 0xa0400400 번지에 로드되어 수행된다는 가정하에 링크되어) flash 메모리 상에서 수행되지 않고 SDRAM을 복사되어 SDRAM 상에서 수행 trampoline.S 파일에서 수행이 시작되자마자 main.c 파일의 함수 main()을 부름 프로그램은 C 언어로 작성되어 있음 BLOB의 대부분의 기능을 수행 blob, kernel, ramdisk를 flash 메모리에서 SDRAM으로 복사 이더넷 초기화 직렬 포트에서 입력이 없으면 SDRAM의 kernel 부분으로 jump하고 그렇지 않으면 명령어 모드로 수행

Makefile - 1 blob_start_elf32_OBJECTS = start.o testmem.o blob_start_elf32_DEPENDENCIES = start-ld-script blob_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)

Makefile - 2 OBJCOPY = arm-linux-objcopy OCFLAGS = -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

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 BLOB-start (1Kbyte) BLOB-rest (63Kbyte)

"start 부분" 로드 스크립트 ENTRY(_start) SECTIONS { . = 0x00000000; // location counter = 0x00000000 . = ALIGN(4); // align 4를 함 .text : { *(.text) } // 모든 text를 여기에 모음 .rodata : { *(.rodata) } // 모든 read only 데이터 모음 .data : { *(.data) } // 모든 초기화된 데이터 모음 .got : { *(.got) } // 모든 global offset table을 모음 .bss : { *(.bss) } // 모든 초기화 되지 않은 데이터 모음 }

"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 } ...

최종 blob 이미지 모습 blob-start blob-rest null 1K ??? 64K blob 끝 1K ??? 64K blob 끝 "start 부분"에서 "rest 부분"으로 수행이 넘어가기 전에 flash 메모리의 1K ~ 64K의 내용을 SDRAM의 0xa0400400에 복사한다

jump 벡터 (start.S) ARM의 7가지 예외 발생시 수행하여야 하는 명령어가 저장된 곳 메모리 0x00000000 번지(flash 메모리 부분)부터 32바이트 저장됨 저장된 명령어는 예외 처리 루틴의 첫 주소로 jump하는 명령어임 _start: b reset // reset b undefined_instruction // undefined instruction b software_interrupt // software interrupt (swi) b prefetch_abort // instruction fetch memory abort b data_abort // data access memory abort b not_used // not used b irq // interrupt b fiq // fast interrupt

reset 예외 처리 (start.S) reset 예외는 init_xscale, init_gpio, init_mem을 부르고 flash 메모리에 저장된 BLOB의 "rest 부분"을 SDRAM의 BLOB_START(=0xa0400400)로 복사하고 이곳으로 jump reset: bl init_xscale bl init_gpio bl init_mem ... relocate: // BLOB reset 부분 relocate adr r0, _start add r2, r0, #(64*1024) add r0, r0, #0x0400 ldr r1, BLOB_START // r0 = source address // r1 = target address // r2 = source end address copy_loop: ldmia r0!, {r3-r10} stmia r1!, {r3-r10} cmp r0, r2 ble copy_loop ldr r0, BLOB_START mov pc, r0

기타 예외 처리 (start.S) "reset 예외"를 제외한 다른 예외는 모두 endless_blink로 jump함 endless_blink로 가면 LED를 계속 깜박거리게 함 undefined_instruction: b endless_blink software_interrupt: ... riq: fiq: endless_blink: bl wait bl flash_led b endless_blink wait: // busy wait loop mov r5, #0x1000000 wait0: subs r5, r5, #1 bne wait0 mov pc, lr

bss 및 stack 설정 (trampoline.S) r0=bss 바이트 수, r1=bss 시작 주소, r2=0을 설정한 후, SDRAM의 bss 영역을 r2로 채우고, SP=stack_end-4로 설정하고 C 코드로 작성된 파일 main.c에 정의된 함수 main을 call _trampoline: ldr r1, bss_start ldr r0, bss_end sub r0, r0, r1 mov r2, #0 // r0 = bss 바이트 수 // r1 = bss start 주소 // r2 = 0 clear_bss: // bss 부분을 clear stmia r1!, {r2} subs r0, r0, #4 bne clear_bss // 스택 설정 ldr r0, stack_end sub sp, r0, #4 // C 코드 함수 main() call bl main

함수 main (main.c) - 1 직렬 포트 초기화, 메시지 출력, 메모리 크기 점검, elf section 출력, 이더넷 초기화 등의 일을 하고 blob, kernel, ramdisk 이미지를 flash 메모리에서 SDRAM으로 복사 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");

함수 main (main.c) - 2 지정된 delay 동안 키 입력이 있는지 점검하고 키이 입력이 없으면 boot를 불러서 SDRAM의 kernel 번지로 jump 키이 입력이 있으면 함수 GetCommand를 불러서 명령어 입력 받음 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, ...); }

주요 명령 처리 함수 명령 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)

함수 reboot (reboot.c) 함수 void Reboot(void)를 flash 메모리의 0x00000000 번지로 정의하고 이 함수를 call한다 power on reset과 같은 효과가 있음 int reboot(int argc, char *argv[]) { void (*Reboot)(void) = (void (*)(void))0x00000000; SerialOutputString("Rebooting...\n\n"); Reboot(); }

함수 boot_linux (linux.c) 함수 void theKernel(int,int)를 SDRAM의 KERNEL_RAM_BASE (=0xa0008000) 번지로 정의하고 이 함수를 call한다 (인수는 0과 ARCH_NUMBER=110) 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); }

함수 Flash (main.c) argv[1]의 값에 따라 blob, kernel, ramdisk, usr 등으로 인식하고 이에 따라 src, dst, numByte를 결정한다 함수 flash_write_region을 부른다 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; } else if ... { ... } nwords = (numBytes + sizeof(u32) - 1) / sizeof(u32); flash_write_region(dst, src, nwords);

함수 flash_write_region (flash.c) SDRAM의 주소(=src)에서 nword 만큼의 데이터를 flash 메모리의 주소(=dst)에 write한다. 함수 flash_write_intel32를 부름 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; } rv = flash_write_intel32(&dst[i], &src[i]); ... }

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 완료 후 필요한 명령임

함수 flash_write_intel32 (flash.c) PGM_SETUP(=0x00400040), STATUS_READ(=0x00700070), READ_ARRAY(=0x00ff00ff) 명령을 사용하여 원하는 flash 메모리에 데이터를 write한다 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); // 정상 상태(=읽기 모드)로 설정 }

함수 do_reload (main.c) what이 무엇이냐에 따라 flash 메모리의 주소, SDRAM의 주소, flash 메모리에서의 크기를 설정하고 함수 MyMemCpy를 call 한다 함수 MyMemCpy는 flash 메모리의 이미지를 SDRAM으로 복사한다 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); }

함수 reblob (reboot.c) 함수 void blob(void)를 SDRAM의 BLOB_RAM_BASE (=0xa0300000) 번지로 정의하고 이 함수를 call한다 SDRAM의 BLOB_RAM_BASE에 복사된 BLOB가 수행 가능한 이유는 "start 부분"이 어셈블리 언어로 작성되어 있고 주소가 현재 PC 값에 대한 상대적인 값으로 지정되어 있기 때문 static int reblob(int argc, char *argv[]) { void (*blob)(void) = (void (*)(void))BLOB_RAM_BASE; SerialOutputString("Restarting blob from RAM...\n\n"); blob(); }