Small bootloader - Raspberry Pi Forums
i created tiny bootloader , thought i'd share class.
small fits inside first 0x100 bytes (252 bytes exact, + 48 bytes of code handles relocation 0x0).
preserves atags setup , register values, means can theoretically load linux kernel (not tested), though might take while @ 115.2kbps
not use special protocol transfer means terminal can send raw file work. of course biggest weakness there no error checking or recovery.
use uart0, larger fifo can reduce risks involved in not checking errors. kudos dwelch67 making example uart0 way.
code made 1 single block of assembly, removes need stack management , frees couple of words. reserve space standard patchable vector table though. apart that, think breaks most, if not all, of "good programming practice" rules, hardcoding of values, no functions , writing null pointer.
might notice bootloader not use ldr method initialize variables. avoids issue assembler place actual value outside region gets relocated. besides, need have more 2x8bit blocks in constant gets loaded before mov + orr gets bigger.
comments?
here is, loaded @ default 0x8000:
small fits inside first 0x100 bytes (252 bytes exact, + 48 bytes of code handles relocation 0x0).
preserves atags setup , register values, means can theoretically load linux kernel (not tested), though might take while @ 115.2kbps
not use special protocol transfer means terminal can send raw file work. of course biggest weakness there no error checking or recovery.
use uart0, larger fifo can reduce risks involved in not checking errors. kudos dwelch67 making example uart0 way.
code made 1 single block of assembly, removes need stack management , frees couple of words. reserve space standard patchable vector table though. apart that, think breaks most, if not all, of "good programming practice" rules, hardcoding of values, no functions , writing null pointer.
might notice bootloader not use ldr method initialize variables. avoids issue assembler place actual value outside region gets relocated. besides, need have more 2x8bit blocks in constant gets loaded before mov + orr gets bigger.
comments?
here is, loaded @ default 0x8000:
code: select all
.section .init .globl _start _start: bootloader_start: ldr pc,reset_handler ldr pc,undefined_handler ldr pc,swi_handler ldr pc,prefetch_handler ldr pc,data_handler ldr pc,unused_handler ldr pc,irq_handler ldr pc,fiq_handler reset_handler: .word loader_loader undefined_handler: .word 0x40 swi_handler: .word 0x40 prefetch_handler: .word 0x40 data_handler: .word 0x40 unused_handler: .word 0x40 irq_handler: .word 0x40 fiq_handler: .word 0x40 # gets loaded @ address 0x40 hang: mov r0, #0x40 bx r0 # gets loaded @ address 0x48 reset: # begin: uart initialization status .req r0 machtype .req r1 atags .req r2 val .req r3 uart_phys_base .req r4 gpio_phys_base .req r5 timer_phys_base .req r6 active_time .req r7 current_time .req r8 load_ptr .req r9 mov uart_phys_base,#0x20000000 orr uart_phys_base,uart_phys_base,#0x00200000 orr uart_phys_base,uart_phys_base,#0x00001000 mov gpio_phys_base,#0x20000000 orr gpio_phys_base, gpio_phys_base, #0x00200000 mov timer_phys_base,#0x20000000 orr timer_phys_base, timer_phys_base, #0x00003000 mov load_ptr,#0x8000 # uart0_cr = 0 mov val,#0 str val, [uart_phys_base, #0x30] # gpio function uart0 pins 14 , 15 mov val,#0x24000 str val, [gpio_phys_base, #4] # uart0_icr = 0x7f1 mov val,#0x7f0 orr val, val, #0x001 str val, [uart_phys_base, #0x44] # uart0_ibrd = 1 mov val,#1 str val, [uart_phys_base, #0x24] # uart0_fbrd = 40 mov val,#40 str val, [uart_phys_base, #0x28] # uart0_lcrh = 0x70 mov val,#0x70 str val, [uart_phys_base, #0x2c] # uart0_cr = 0x301 mov val,#0x300 orr val, val, #0x001 str val, [uart_phys_base, #0x30] # end: uart initialization # transmit 'b' on uart mov val, #0x42 str val, [uart_phys_base, #0x00] # initialize time timeout ldr current_time, [timer_phys_base, #4] mov active_time, current_time loop$: # read uart0_fr ldr val, [uart_phys_base, #0x18] ands val, val, #0x10 # if result non-zero, continue timeout check bne cont$ # load actual uart data byte , mask byte ldr val, [uart_phys_base, #0x00] , val, val, #0xff # *load_ptr = val, load_ptr++ strb val, [load_ptr], #1 # set active time mov active_time, current_time cont$: # check timeout ldr current_time, [timer_phys_base, #4] sub val, current_time, active_time cmp val, #0x50000 bls loop$ # ... if have started receiving data cmp load_ptr, #0x8000 beq loop$ # transmit 's' on uart mov val, #0x53 str val, [uart_phys_base, #0x00] # branch loaded code entry point mov val, #0x8000 bx val bootloader_end: loader_loader: mov r3, # 0x8000 mov r4, # bootloader_end - bootloader_start mov r5, #0 copy: ldr r6, [r3], #4 @ load starting 0x8000, postincrement 4 str r6, [r5], #4 @ store starting 0x0, postincrement 4 subs r4, r4, #4 @ if ((r4 -= 4) != 0) bne copy @ goto copy mov r3, #0x20 mov r4, #0x48 str r4, [r3] @ *(0x20) = 0x48, point reset vector "reset" # goto address 0x0 reset vector mov r7, #0 bx r7
raspberrypi
Comments
Post a Comment