1 / 32

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

부트 로더 (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)

meli
Download Presentation

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

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 부트 로더 (blob-2.0.5-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-2.0.5-pre2가 가장 최근 버전임 • URL: http://www.lart.tudelft.nl/lartware/blob

  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:도움말 출력

  5. BLOB 컴파일 방법 • 리눅스 kernel 소스 트리 필요 • "/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가 새로 만들어진 이미지임)

  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. 메모리초기화 start.S 하드웨어초기화 시리얼 초기화 타임머 초기화 main() 커널,램디스크를 램에 복사 10 10 초간 가다린후 실행 10 10 키가 키가 초안에 초안에 누렸을때 누렸을때 명령어 명령어 모드 모드 run command GetCommand GetCommand () () 커널로 점프 () () SetClock SetClock () Download() Download() Flash() Flash() ...... ...... boot_linux () boot_linux Auto Boot Manual Boot BLOB 실행 흐름

  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에 있는 0xa0400400 번지(=BLOB_START)로 복사 • BLOB_START(rest 부분)로 jump

  11. rest 부분 • flash 메모리 0x00000400 번지부터 저장 (주: 저장만 여기에 되어있지 실제는 0xa0400400 번지에 로드되어 수행된다는 가정하에 링크되어) • 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 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) $< $@

  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

  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) } // 모든 초기화 되지 않은 데이터 모음 }

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

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

  18. 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

  19. 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

  20. 기타 예외 처리 (start.S) • "reset 예외"를 제외한 다른 예외는 모두 endless_blink로 jump함 • endless_blink로 가면 LED를 계속 깜박거리게 함 undefined_instruction: b endless_blink software_interrupt: b endless_blink ... riq: b endless_blink fiq: b endless_blink 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

  21. bss 및 stack 설정 (trampoline.S) _trampoline: ldr r1, bss_start ldr r0, bss_end sub r0, r0, r1 mov r2, #0 // r0 = bss 바이트 수 // r1 = bss start 주소 // r2 = 0 • r0=bss 바이트 수, r1=bss 시작 주소, r2=0을 설정한 후, • SDRAM의 bss 영역을 r2로 채우고, SP=stack_end-4로 설정하고 • C 코드로 작성된 파일 main.c에 정의된 함수 main을 call 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 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를 불러서 명령어 입력 받음

  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) 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과 같은 효과가 있음

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

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

  30. 함수 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); // 정상 상태(=읽기 모드)로 설정 }

  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) 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 값에 대한 상대적인 값으로 지정되어 있기 때문

More Related