280 likes | 529 Views
9. 부트로더 분석. 9. 부트로더 분석. BLOB 실행 흐름 BLOB Memory map BLOB object 구조 주요 소스 코드 분석 BLOB 기능 추가 하기. 메모리. 메모리. 초기화. 초기화. start.S. 하드웨어. 하드웨어. 초기와. 초기와. 시리얼. 시리얼. 초기화. 초기화. main(). 타임머. 타임머. 초기화. 초기화. ,. ,. 커널. 커널. 램디스크를. 램디스크를. 램에. 램에. 복사. 복사. 10. 10. 10. 10. 초간.
E N D
9. 부트로더 분석 • BLOB 실행 흐름 • BLOB Memory map • BLOB object 구조 • 주요 소스 코드 분석 • BLOB 기능 추가 하기 www.huins.com
메모리 메모리 초기화 초기화 start.S 하드웨어 하드웨어 초기와 초기와 시리얼 시리얼 초기화 초기화 main() 타임머 타임머 초기화 초기화 , , 커널 커널 램디스크를 램디스크를 램에 램에 복사 복사 10 10 10 10 초간 초간 가다린후 가다린후 실행 실행 키가 키가 초안에 초안에 누렸을때 누렸을때 명령어 명령어 모드 모드 run command run command GetCommand GetCommand () () 커널로 커널로 점프 점프 () () SetClock SetClock () Download() Download() Flash() Flash() ...... ...... boot_linux () () boot_linux Auto Boot Auto Boot Manual Boot Manual Boot 9. 부트로더 분석 www.huins.com
9. 부트로더 분석 SDRAM (128M) FLASH ROM (32M) www.huins.com
9. 부트로더 분석 • BLOB는 2가지 stage로 구분 된다. • start.S 로 시작하는 하드웨어의 기본적인 초기화를 담당하는 start stage • Trampoline.S로 시작하는실질 적인 기능을 담당하는 rest stage • Start stage • flash memory의 0x0번지 부터 위치하여 수행된다. • cpu, memory 등 기본적인 하드웨어 초기화 • 모두 assembly 코드 • Rest stage • flash memory의 0x400번지 부터 위치하고 sdram으로 copy된 후 실행 된다. • 실제적인 boot loader의 기능을 수행한다. • 대부분 c 코드로 구성 www.huins.com
9. 부트로더 분석 _start(start.S)를 가장 처음 실행할 루틴으로 지정 • start-ld-script OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS { . = 0x00000000; . = ALIGN(4); .text : { *(.text) } . = ALIGN(4); .rodata : { *(.rodata) } . = ALIGN(4); .data : { *(.data) } . = ALIGN(4); .got : { *(.got) } . = ALIGN(4); .bss : { *(.bss) } } www.huins.com
9. 부트로더 분석 • rest-ld-script OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_trampoline) SECTIONS { . = (0xa0400400); . = ALIGN(4); .text : { __text_start = .; *(.text) __text_end = .; } … } www.huins.com
9. 부트로더 분석 • Makefile … blob_start_elf32_OBJECTS = start.o testmem.o … 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: $(blob_start_elf32_OBJECTS) $(blob_start_elf32_DEPENDENCIES) @rm -f blob-start-elf32 $(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) @rm -f blob-rest-elf32 $(LINK) $(blob_rest_elf32_LDFLAGS) $(blob_rest_elf32_OBJECTS) \ $(blob_rest_elf32_LDADD) $(LIBS) www.huins.com
9. 부트로더 분석 • Makefile (cont’) … blob-start : blob-start-elf32 $(OBJCOPY) $(OCFLAGS) $< $@ … blob-rest : blob-rest-elf32 $(OBJCOPY) $(OCFLAGS) $< $@ … blob: blob-start blob-rest rm -f $@ dd if=blob-start of=$@ bs=1k conv=sync dd if=blob-rest of=$@ bs=1k seek=1 chmod +x $@ … www.huins.com
BLOB-start (1Kbyte) BLOB-rest (63Kbyte) 9. 부트로더 분석 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 www.huins.com
9. 부트로더 분석 • start.S .text // Jump vector table as in table 3.1 in [1] g .globl _start _start: b reset b undefined_instruction b software_interrupt b prefetch_abort b data_abort b not_used b irq b fiq www.huins.com
9. 부트로더 분석 • start.S reset: // At the end of the reset sequence, MMU, Icache, Dcache, // and write buffer are all disabled. // Also IRQs and FIQs are disabled in the processor's CPSR // The operating mode is SVC (supervisory mode), and the // PC is vectored at 0x00000000. A branch in 0x00000000 // brings us directly here. // PXA255 Initialization bl init_xscale // GPIO Initialization bl init_gpio // SDRAM Initialization bl init_mem normal_boot: // check the first 1MB of BLOB_START in increments of 4k … www.huins.com
9. 부트로더 분석 • start.S relocate: adr r0, _start // relocate the second stage loader add r2, r0, #(64 * 1024) // blob maximum size is 64kB add r0, r0, #0x400 // skip first 1024 bytes ldr r1, BLOB_START copy_loop: ldmia r0!, {r3-r10} stmia r1!, {r3-r10} cmp r0, r2 ble copy_loop // blob is copied to ram, so jump to it ldr r0, BLOB_START mov pc, r0 www.huins.com
9. 부트로더 분석 • trampoline.S .text .globl _trampoline _trampoline: /* clear the BSS section */ ldr r1, bss_start ldr r0, bss_end sub r0, r0, r1 /* r1 = start address */ /* r0 = #number of bytes */ mov r2, #0 www.huins.com
9. 부트로더 분석 • trampoline.S clear_bss: stmia r1!, {r2} subs r0, r0, #4 bne clear_bss /* setup the stack pointer */ ldr r0, stack_end sub sp, r0, #4 /* jump to C code */ bl main /* if main ever returns we just call it again */ b _trampoline bss_start: .word __bss_start bss_end: .word __bss_end stack_end: .word __stack_end www.huins.com
9. 부트로더 분석 • main()/main.c int main(void){ … init_subsystems(); clientIP = inet_addr(CLIENT_IPADDR); hostIP = inet_addr(HOST_IPADDR); TimerInit2(); blob_status.paramType = fromFlash; // or download blob_status.kernelType = fromFlash; blob_status.ramdiskType = fromFlash; blob_status.rootType = fromFlash; blob_status.usrType = fromFlash; blob_status.downloadSpeed = baud_115200; blob_status.terminalSpeed = baud_115200; blob_status.load_ramdisk = 1; blob_status.cmdline[0] = '\0'; blob_status.boot_delay = 1; www.huins.com
9. 부트로더 분석 • main()/main.c /* parse the core tag, for critical things like terminal speed */ #ifdef PARAM_START parse_ptag((void *) PARAM_START, &conf); #endif … /* get the amount of memory */ get_memory_map(); … #ifdef PARAM_START parse_ptags((void *) PARAM_START, &conf); #endif … /* Load kernel and ramdisk from flash to RAM */ do_reload("blob"); //BLOB_RAM_BASE에 blob를 적재 do_reload("kernel"); //KERNEL_RAM_BASE에 kernel 적재 do_reload("ramdisk"); //RAMDISK_RAM_BASE에 ramdisk 적재 www.huins.com
9. 부트로더 분석 • main()/main.c EthInit(); /* wait 10 seconds before starting autoboot */ SerialOutputString("Autoboot in progress, press any key to stop "); for(i = 0; i < blob_status.boot_delay; i++) { serial_write('.'); retval = SerialInputBlock(commandline, 1, 1); if(retval > 0) break; } if(retval == 0) { commandline[0] = '\0'; parse_command("boot"); } www.huins.com
9. 부트로더 분석 • main()/main.c … /* the command loop. endless, of course */ for(;;) { DisplayPrompt("boot> "); /* wait 10 minutes for a command */ numRead = GetCommand(commandline, MAX_COMMANDLINE_LENGTH, 600); if(numRead > 0) { if((retval = parse_command(commandline)) < 0 ) printerror(retval, NULL); } } return 0; } /* main */ www.huins.com
9. 부트로더 분석 • init_subsystems()/init.c void init_subsystems(void) { int i; /* call all subsystem init functions */ for(i = INIT_LEVEL_MIN; i <= INIT_LEVEL_MAX; i++) call_funcs( (initlist_t *)&__initlist_start, (initlist_t *)&__initlist_end, INIT_MAGIC, i);} /* init.h */ … #define __init __attribute__((unused, __section__(".initlist"))) #define __initlist(fn, lvl) \ static initlist_t __init_##fn __init = { \ magic: INIT_MAGIC, \ callback: fn, \ level: lvl } /* rest-ld-script */ … . = ALIGN(4); .initlist : { __initlist_start = .; *(.initlist) __initlist_end = .; } www.huins.com
9. 부트로더 분석 • call_funcs()/init.c static void call_funcs(initlist_t *start, initlist_t *end, u32 magic, int level) { initlist_t *item; for(item = start; item != end; item++) { if(item->magic != magic) { printerror(EMAGIC, NULL); … return; } if(item->level == level) { /* call function */ item->callback(); } } } /* init.h */ … typedef void(*initfunc_t)(void); typedef struct { u32 magic; initfunc_t callback; int level; } initlist_t; /* pxa255_pro.c */ … static void pxa255_pro_init_hardware(void) { /* select serial driver */ serial_driver = &pxa255_pro_serial_driver; } __initlist(pxa255_pro_init_hardware, INIT_LEVEL_DRIVER_SELECTION); www.huins.com
9. 부트로더 분석 • command.h /* command.h */ … typedef int(*commandfunc_t)(int, char *[]); typedef struct commandlist { u32 magic; char *name; char *help; commandfunc_t callback; struct commandlist *next; } commandlist_t; #define __command __attribute__((unused, __section__(".commandlist"))) #define __commandlist(fn, nm, hlp) \ static commandlist_t __command_##fn __command = { \ magic: COMMAND_MAGIC, \ name: nm, \ help: hlp, \ callback: fn } www.huins.com
9. 부트로더 분석 • init_command()/commands.c /* rest-ld-script */ … . = ALIGN(4); .commandlist : { __commandlist_start = .; *(.commandlist) __commandlist_end = .; } commandlist_t *commands; static void init_commands(void) { commandlist_t *lastcommand; commandlist_t *cmd, *next_cmd; commands = (commandlist_t *) &__commandlist_start; lastcommand = (commandlist_t *) &__commandlist_end; cmd = next_cmd = commands; next_cmd++; while(next_cmd < lastcommand) { cmd->next = next_cmd; cmd++; next_cmd++; } } __initlist(init_commands, INIT_LEVEL_OTHER_STUFF); /* main.c */ … static int Flash_erase(int argc, char *argv[]) { … } static char erasehelp[] = "erase <start> <len>“ \ "flsah erase \n“ \ "erase <start> <len>, ex) erase 180000 200000\n"; __commandlist(Flash_erase, "erase", erasehelp); www.huins.com
9. 부트로더 분석 • parse_command()/commands.c int parse_command(char *cmdline) { commandlist_t *cmd; int argc, num_commands, len; char *argv[MAX_ARGS]; parse_args(cmdline, &argc, argv); /* only whitespace */ if(argc == 0) return 0; www.huins.com
9. 부트로더 분석 • parse_command()/commands.c num_commands = get_num_command_matches(argv[0]); /* error */ if(num_commands < 0) return num_commands; /* no command matches */ if(num_commands == 0) return -ECOMMAND; /* ambiguous command */ if(num_commands > 1) return -EAMBIGCMD; len = strlen(argv[0]); www.huins.com
9. 부트로더 분석 • parse_command()/commands.c /* single command, go for it */ for(cmd = commands; cmd != NULL; cmd = cmd->next) { if(cmd->magic != COMMAND_MAGIC) { return -EMAGIC; } if(strncmp(cmd->name, argv[0], len) == 0) { /* call function */ return cmd->callback(argc, argv); } } return -ECOMMAND; } www.huins.com
9. 부트로더 분석 • boot_kernel()/linux.c static int boot_linux(int argc, char *argv[]) { void (*theKernel)(int zero, int arch) = (void (*)(int, int))KERNEL_RAM_BASE; … … /* start kernel */ theKernel(0, ARCH_NUMBER); SerialOutputString("Hey, the kernel returned! This should not happen.\n"); return 0; } static char boothelp[] = "boot [kernel options]\n" "Boot Linux with optional kernel options\n"; __commandlist(boot_linux, "boot", boothelp); www.huins.com
9. 부트로더 분석 • Example (command add) Static int example_command(int argc, char *argv[]) { int i; for( I = 0; I < argc; i++ ){ SerialOutputString(“argv[“); SerialOutputDec(i); SerialOutputString(“] = \””); SerialOutputString(“\”\n”); } return 0; } static char examplehelp[] = “example command\n”; __commandlist(example_command, “example”, examplehelp); www.huins.com