Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "부트 로더 (blob-2.0.5-pre2 중심) Lecture #8."— Presentation transcript:

1 부트 로더 (blob pre2 중심) Lecture #8

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

3 BLOB 소개 네덜란드의 Delft University of Technology에서 개발
LART(Linux Advanced Radio Terminal)라는 리눅스 기반 공개 소스 내장형 컴퓨터(인텔 SA-1100 마이크로 프로세서 사용)에 사용된 부트 로더 현재 blob pre2가 가장 최근 버전임 URL:

4 주요 명령 reset: 직렬 포트에 화면을 clear하는 문자(ESC-c)를 보냄
reboot: 0x 로 제어를 옮김 (=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: 0xa 으로 제어를 옮김 (=SDRAM에 복사된 BLOB 수행) btp: BOOTP 서버로 부터 키트의 IP 주소를 받아옴 help: 도움말 출력

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

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

7 BLOB 메모리 맵

8 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로 부팅하지 않고 사용자에게 명령을 받을 준비를 하고 기다리게 된다.

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

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

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

12 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)

13 Makefile - 2 OBJCOPY = arm-linux-objcopy
OCFLAGS = -O binary -R .note -R .comment -S blob: blob-start blob-rest dd if=blob-start bs=1k conv=sync dd if=blob-rest bs=1k seek=1 chmod +x blob-start: blob-start-elf32 $(OBJCOPY) $(OCFLAGS) $< blob-rest: blob-rest-elf32

14 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)

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

16 "rest 부분" 로드 스크립트 SECTIONS {
. = (0xa ); // location counter = 0xa . = ALIGN(4); // align 4를 함 .text : { __text_start = .; // __text_start = 현재 location counter *(.text) // 모든 text를 여기에 모음 __text_end = .; // __text_end = 현재 location counter } ...

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

18 jump 벡터 (start.S) ARM의 7가지 예외 발생시 수행하여야 하는 명령어가 저장된 곳
메모리 0x 번지(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

19 reset 예외 처리 (start.S) reset 예외는 init_xscale, init_gpio, init_mem을 부르고
flash 메모리에 저장된 BLOB의 "rest 부분"을 SDRAM의 BLOB_START(=0xa )로 복사하고 이곳으로 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

20 기타 예외 처리 (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, #0x wait0: subs r5, r5, #1 bne wait0 mov pc, lr

21 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

22 함수 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");

23 함수 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, ...); }

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)

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

26 함수 boot_linux (linux.c)
함수 void theKernel(int,int)를 SDRAM의 KERNEL_RAM_BASE (=0xa ) 번지로 정의하고 이 함수를 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); }

27 함수 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);

28 함수 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]); ... }

29 Intel flash 메모리(16bit 칩*2) write 방법
PGM_SETUP(=0x ): 이 명령을 flash 메모리(어떤 번지나 무방)에 쓰면 flash 메모리가 write될 준비를 한다 write할 번지에 원하는 데이터를 쓴다 (*dst = *src; ) STATUS_READ(=0x ): 이 명령을 flash 메모리(어떤 번지나 무방)에 쓴 후 flash 메모리(어떤 번지나 무방)의 내용을 읽으면 현재 flash 메모리의 상태가 읽혀진다. 현재 BLOB에서 write 후 점검하는 상태는 STATUS_BUSY(=0x ) 및 STATUS_PGM_ ERR(=0x )이다 READ_ARRAY(=0x00ff00ff): 이 명령을 flash 메모리에(어떤 번지나 무방함) 쓰면 flash 메모리가 read할 수 있는 상태로 된다. write 완료 후 필요한 명령임

30 함수 flash_write_intel32 (flash.c)
PGM_SETUP(=0x ), STATUS_READ(=0x ), 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); // 정상 상태(=읽기 모드)로 설정 }

31 함수 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); }

32 함수 reblob (reboot.c) 함수 void blob(void)를 SDRAM의 BLOB_RAM_BASE (=0xa ) 번지로 정의하고 이 함수를 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(); }


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

Similar presentations


Ads by Google