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

Slides:



Advertisements
Similar presentations
엑셀리포트를 이용한 날짜별 리포트 자동 저장 방법
Advertisements

컴퓨터와 인터넷.
패러럴 포트를 이용한 Text LCD 제어 6월 17일 허정수 나선웅.
9. 부트로더 분석.
EZ Board-M In-Ho, Roh Real Time System Lab.
김태원 심재일 김상래 강신택. 김태원 심재일 김상래 강신택 인터넷 통신망의 정보를 제공하는 서비스 인터넷의 자원 및 정보는 NIC가 관리 IP주소 또는 도메인으로 정보 검색 이용자 및 통신망 관한 정보를 제공.
1. 신뢰할 수 있는 싸이트 등록 인터넷 익스플로러 실행 후 실행
부트로더 Blob.
제6장 FUSING.
Cross Compiler를이용한 커널 컴파일 및 포팅
1장. 이것이 C 언어다.. 1장. 이것이 C 언어다. 프로그래밍 언어 1-1 C 언어의 개론적 이야기 한글, 엑셀, 게임 등의 프로그램을 만들 때 사용하는 언어 ‘컴퓨터 프로그래머’라는 사람들이 제작 C 언어(C++ 포함)를 가장 많이 사용함.
제7강 학습 내용 주소지정 방식의 예 값 즉시 지정 방식과 실행 예 레지스터 직접지정 방식 메모리 직접지정 방식과 실행 예
Linux/UNIX Programming
뇌를 자극하는 Windows Server 2012 R2
FUSING.
QT 프로그래밍 발표: 김래영.
임베디드 리눅스 설치 및 동작 Lecture #5.
임베디드 시스템 개론 크로스 플랫폼 설치 2일차 강의 자료 Embedded System Lab.
UNIT 07 Memory Map 로봇 SW 교육원 조용수.
Embedded System Porting (2)
강 명 수 LINUX 설치 강 명 수
CHAPTER 02 OpenCV 개요 PART 01 영상 처리 개요 및 OpenCV 소개.
Root Filesystem Porting
부트 로더 (blob pre2 중심) Lecture #8.
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
Root Filesystem Porting
부트로더와 Self Programming
ARM Development Suite v1.2
Cross Compiler 설치.
DK-128 실습 EEPROM 제어 아이티즌 기술연구소
Host PC & Target Board 환경설정 Embedded Linux Image 올리기
TCP/IP Socket Programming…
Boot Loader.
Cross Compiler를이용한 커널 컴파일 및 포팅
사용자 함수 사용하기 함수 함수 정의 프로그램에서 특정한 기능을 수행하도록 만든 하나의 단위 작업
Chap 6.Assembler 유건우.
UNIT 07 Memory Map 로봇 SW 교육원 조용수.
이름 : 황 상 두 전화번호 : 이메일 : PinTool 이름 : 황 상 두 전화번호 : 이메일 :
강의 개요. 2014년 가을학기 손시운 지도 교수: 문양세 교수님.
Device Driver 임베디드 시스템 I.
9. 부트로더 분석.
영상처리 실습 인공지능연구실.
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express Slide 1 (of 22)
임베디드 시스템 개론 임베디드 타겟 보드 포팅 및 H/W 제어 3일차 강의 자료 Embedded System Lab.
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
DK-128 실습 내부 EEPROM 제어 아이티즌 기술연구소 김태성 연구원
패러럴 포트를 이용한 Text LCD 제어 6월 17일 허정수 나선웅.
클라우드 서버로 부터 값 읽어오기 WiFi 시리얼 보드 활용가이드 김영준 헬로앱스 (
ARM Development Suite v1.2
컴퓨터 프로그래밍 기초 - 8th : 함수와 변수 / 배열 -
리눅스 커널 프로그래밍 환경 구축 IT EXPERT 리눅스 커널 프로그래밍 Author : Byungki Kim
웹서버 기능으로 데이터 읽기 및 제어하기 WiFi 시리얼 보드 활용가이드 김영준
네트워크 환경 구축과 이미지 전송 호스트/타겟 통신 직렬 통신을 이용한 이미지 전송 수퍼 데몬 BOOTP 환경 구축
Canary value 스택 가드(Stack Guard).
Kernel, Ramdisk, JFFS2 Porting
( Windows Service Application Debugging )
DK-128 개발환경 설정 아이티즌 기술연구소
7주차: Functions and Arrays
ARM Development Suite v1.2
Tensorboard in Windows
3.2 분기 명령어.
AdcRead API 함수 분석 마이크로프로세서.
EZ-8051 Board를 이용한 E-Board의 제어
임베디드 시스템 개론 3주차.
ARM Development Suite v1.2
06. 디바이스의 등록과 해제 김진홍
1장 C 언어의 개요 C 언어의 역사와 기원 C 언어의 특징 프로그램 과정 C 프로그램 구조 C 프로그램 예제.
Docker Study 6~7.
7 생성자 함수.
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(); }