bootloader笔记

从图书馆随便借的(实际bootloader只有就这一本

 

也不过就是给txt打了个tag(x


bootloader TP368.1/742

PC boot seqense:

    BIOS -> MBR -> GRUB -> Linux -> User

    uefi sequense:

    (?


vim:

    #[TODO] vimtutor

    plugin:

        ctags

        taglist

        cscope


gcc:

    man gcc

    gcc:

        -x language

        -c -S -E -o

        -ffreestanding -fno-builtin > build bootloader

        -Wall

    -g -p -pg

    ld:

        -nostdinc

        -nostdlib -nodefaultlibs -nostartfiles

        -share

        -T script


Linux command:

    man find

man grep

        -e externed regexp

        -i –ignore-case

        -v reverse

        -x full line

        -m num

        -D action (special/device file)

        -d action (folder)

        -r recursive

    Regexp: 

        nothing new

    pipe line, redirect:

        stdout : 0

        stdin : 1

        stderr : 2

        > redirect stdout to file

        < redirect stdin from file

        >> append stdout to file

        >| force >

        n>| force file as descriptor n

        <> use file as stdin and stdout

        n>file 

        n<file

        n>>file

        n>& copy stdout to file n

        n<& copy n to stdin

        n>&m n used as copy of outstream m

        n<&m n used as copy of instream m

        &>file stdout, stderr to file

        <&- close stdin

        >&- close stdout

        n>&- close n output

        n<&- close n input


Makefile:

        recursive make (?

        phony

        functions:

            $(..)   return

            subst from, to, text    replace all ’from’ to ’to’ in text

            patsubst %.xml, %.dvi, text  replace all ’.xml’ to ’.dvi’

            strip strint    drop head and tail spaces, merge multiply space character to one space character

            findstring find, in     find.indexOf(in)==-1?find[find.indexOf(in),find.indexOf(in)+in.length]:none

            filter pattern…, text all strings match

            filter-out      reverse use of filter

            sort list       sort by first character and exclude same word

            word N, Text    Text[n-1]

            wordlist s, e, text text[s,e]

            words text      len(text)

            firstword text  text[0]

            dir names       names.map(item=>Path(item).dir())

            notdir names    names.map(item=>Path(item).name())

            suffix names    names.map(item=>item.slice(item.lastIndexOf(‘.’)))

            basename names  names.map(item=>Path(item.slice(0, item.lastIndexOf(‘.’)).name()))

            addsuffix suffix, names     names.map(item=>${item}suffix)

            addprefix prefix, names     names.map(item=>prefix${item})

            join list1, list2   [list1[i]+list2[i] for i in range(min(len(list1), len(list2)))]

            wildcard pattern    find . | grep pattern


arm:

    mode:

        user:       0b10000     normal

        fiq:        0b10001     fast data copy, interrupt

        irq:        0b10010     interrupt

        supervisor: 0b10011     system protection

        abort:      0b10111     virtual storage or protection

        undefined:  0b11011     hardware cp simulation

        system:     0b11111     operating system task

    error:

        fiq, irq, svc, abt, und

    exception table:

        rst: 0x0    system reset

        und: 0x4    undefined instruction

        svc: 0x8    software interrupt

        abt: 0xc    code get error

        abt: 0x10   data get error

        rev: 0x14

        irq: 0x18   interrupt

        fiq: 0x1c   fast interrupt

    register:

        37 registers.

        user mode, system mode common register R1  R7, R8  R12, R13 ~ R14

        svc, abt, und, irq mode special register R13_*, R14_*, SPSR_*

        fiq mode special register R8_fiq ~ R14_fiq, SPSR_fiq

        all mode common pc, cpsr

        r0~r7: common usage.

        r13: sp

        r14: lr

        r15: pc

        cpsr:

        N Z C V Q R R J R R R G E G E R R R R R R E A I F T M M M M

        user access:

            NZCV: condition flags

                N: negative

                Z: zero

                C: carry

                V: signed carry

            Q:  (?

            GE: (?

            E: (?

        privilged access:

            A: EAll

            I: EIrq

            F: EFiq

            M: -> mode

            J T: instruction set. 8bit / 16bit. 

    arm instruction set:

        format: instruction(s) …, shifter

        shifter:

            LSL:     <<

            LSR:     >>

            ASR

            ROR

            RRX

        mov rd, N

        mvn rd, N

            rd = ()N :mvn

            mov r0, r1, LSL #9

            mov r0, #0

            Immediate bigger than 256u and can’t shift by number within 256 need use ”ldr” instruction

        ADC Rd, Rn, N   Rd = Rn + N + carry    

        ADD Rd, Rn, N   Rd = Rn + N

        RSB Rd, Rn, N   Rd = N - Rn

        RSC Rd, Rn, N   Rd = N - Rn - !carry

        SBC Rd, Rn, N   Rd = Rn - N - !carry

        SUB Rd, Rn, N   Rd = Rn - N

            N can be 8bit imm or Rm

        AND Rd, Rn, N   Rd = Rn & N

        ORR Rd, Rn, N   Rd = Rn | N

        EOR Rd, Rn, N   Rd = Rn ^ n

        BIC Rd, Rn, N   Rd = Rn &~ N

            N can be 8bit imm or Rm

        CMN Rd, N   Rd + N -> NZCV

        CMP Rd, N   Rd - N -> NZCV

        TEQ Rd, N   Rd ^ N -> NZCV

        TST Rd, N   Rn & N -> NZCV

        MLA Rd, Rm, Rs, Rn  Rd = (Rm * Rs) + Rn

        MUL Rd, Rm, Rs      Rd = Rm * Rs

        SMLAL RdLo, RdHi, Rm, Rs    

        SMULL RdLo, RdHi, Rm, Rs    

        UMLAL RdLo, RdHi, Rm, Rs   

        UMULL RdLo, RdHi, Rm, Rs     

        B label     PC = label

        BL label    PC = label, lr = PC + 8

        BX Rm       PC = Rm & ~1, T = Rm & 1

        BLX Rm

        SWI num

        MRS Rd, CPSR|SPSR       Rd = .

        MSR CPSR|SPSR_*, Rd     . = Rd

        MSR CPSR|SPSR_*, #imm   . = imm

        !cp register: what the fuck?

        cdp cp, opcode1, Cd, Cn, {, opcode2}

        mrc|mcr cp, opcode1, Rd, Cn, Cm {, opcode2}

        ldc|stc cp, Cd, addressing

        fake ins:

        ldr Rd, =imm    Rd = imm

        adr Rd, label   Rd = &label

    addressing:     

        > ldr|str{cond}{B}{T} 

            # instruction struct:

                cond 0 1 S P U B W L Rn Rd data

                cond: condition

                S: shift

                P: update register sequense

                U: direction

                B: byte

                W: write to register

                L: load ~L: store

            [M, shifter N]        [M shifter N]

                8bit imm + 4bit shift

                register + 4bit shift

                register + register shift

                    ! if R15(PC) as the register number the value is current position + 8

                    ! use shifter will change cpsr

            [Rn, +/- N]           [Rn +/- N]

                12bit imm offset

                register

                    # to access byte array membey by index

            [Rn, +/- Rm, shifter N]       [Rn] +/- (Rm shifter N)

                4bit imm

            [Rn, +/- N]!         Rn {=} [Rn +/- N]

                12bit imm offset

                register

                    ! condition must passed before update Rn

                    ! do NOT use R15(PC) as Rn

            [Rn, +/- Rm, shifter N]!    Rn {=} [Rn +/- (Rm shifter N)]

                4bit imm

                    # auto update Rn before accessing array member

            [Rn], +/- N         [Rn] {=} Rn +/- N

                12bit imm offset

                register

                    # auto update Rn after accessing array member

            [Rn], +/- Rm, shifter N     [Rn] {=} Rn +/- (Rm shifter N)

                4bit imm 

        > ldr|str{cond}H|SH|SB|D Rd, addressing

            # instruction struct:

                cond 0 0 0 P U 1 W L Rn Rd data

                cond: condition

                P: register update sequense

                    ! P = 0 while update register even if W = 0

                U: direction

                W: write to register

                    ! while P = 0, W must = 0. P = 0, W = 1 is not allowed

                L, S, H: 

                    L=0, S=0, H=1   str dbyte

                    L=0, S=1, H=0   ldr dword

                    L=0, S=1, H=1   str dword

                    L=1, S=0, H=1   ldr unsigned dbtye

                    L=1, S=1, H=0   ldr signed byte

                    L=1, S=1, H=1   ldr signed dbyte

                    ! S=0, H=0 represent an unsigned byte operation, this operation will not use this addressing, using previous adressing instead. instruction ldrb, ldrbt, strb, strbt will cause this happend

                    ! S=1, L=0 represent a signed byte str operation. H=0 ldrd, H=1 strd

            [Rn, +/- N]     [Rn +/- N]

                8bit offset imm

                    ! [Rn] represent [Rn, #0]

                    # to access member of a struct

                    # to access vars in stack

                    # to access data addressed by Rn

                register

                    # access array member

            [Rn, +/- N]!    Rn {=} [Rn +/- N]

                8bit offset imm

                    ! [Rn, #0]! is not allowed

                    # auto update Rn after access array member using Rn +/- N if condition passed

                register

            [Rn], +/- N

                8bit offset imm

                    # auto update Rn after access array member using Rn if condition passed 

                register

            !! no scaled operation

        > ldm|stm{cond}IA|IB|DA|DB Rn{!}, registers{^}

            IA: increase after

            IB: increase before

            DA: decrease after

            DB: decrease before

            # instruction struct:

                cond 1 0 0 P U S W L Rn registers

                cond: condition

                P: Rn is in the inbound/outbound

                U: direction

                S: if load pc/r15 with ldms this bit represent copy spsr to cpsr, else in the privilged mode this bit represent to load/store registers in the common mode

                W: write to register

                L: load ~L: store

                registers: 16bit, each bit represent a register. 

                    ! registers = 0x00 is not allowed.

                    # registers are covered by ’{}’. : {r0, r1, pc, sp}

        > mcr|mrc|ldc|stc{cond}(L) cp, CRd, addressing

            ! mcr, mrc is not fully explained in this book.

            # instruction struct

                cond 1 1 0 P U N W L Rn CRd cp_num offset_8

                P: addressing mode + W

                U: direction

                N: size of byte

                W: write to register

                L: load ~L: store

            [Rn, #+/-offset_8*4]

                # size of bytes to transfer is controlled by co-operator

                # maxium 16 words is transfered

            [Rn, $+/-offset_8*4]!

            [Rn], #+/-offset_8*4

            [Rn], option

ld:

    GNU Tools:

        ar, strings, strip, nm, size, readelf

    elf:

        relocatable, executable, shared object

        struction:

            elf.h

            elf header: 

                elf32_ehdr http://www.openvirtualization.org/documentation/structElf32__Ehdr.html

                    ! elf_type

            elf section header table:

                elf32_Shdr http://www.openvirtualization.org/documentation/structElf32__Shdr.html

                    ! sh_type

                        progbits:       program, data, debug info

                        nobits:         .bss

                        strtab,dynsym:  symbol

                        rel, rela:      relocation data

                        dynamic, hash:  

                    ! sh_flags:

                        alloc:          alloc memory during load

                        write:          writable after load

                        execinstr:      executable code

                # segments:

                    .text:      program

                    .data:      global variables with initial value

                    .rodata:    readonly variables

                    .bss:       global variables without initial value

                    .rel.text:  relocation data

                    .rel.data

                    .rel.rodata

                    .init:      > C++

                    .fini       > C++

                    .symtab     

                    .dynsym

                    .strtab:    symbol table name

                    .dynsym

                    .got:       global offset table        

                    .plt:       progress link table

                    .debug

                    .line

                    .comment

                    …

            symbol table struction:

                elf32_sym http://www.openvirtualization.org/documentation/structElf32__Sym.html

        stroage allocation:

            merge same section using relocation table

            relocation table:

                struct elf32_rel

                    elf32_addr r_offset

                    elf32_word r_info

                struct elf32_rela

                    elf32_sword r_addend

                    ! r_info:   relocation type and symbol offset

                    ! r_addend: align

            symbol analysis:

                strong symbol can’t redefined

                    ! strong symbol: function, initilized global variables

                strong symbol will refefine weak symbol

                multiply weak symbol will use biggest symbol

            relocation:

                relocation table can get the symbol offset address

        ld scripts:

            section

            memory          

            .               position counter

                ! 

            ENTRY(symbol)

            INCLUDE

            OUTPUT_FORMAT(elf32-bigmips, elf32-bigmips, elf32-littlemips)

                            default         -EB             -EL

            REGION_ALIAS(alias, region)

                ~ INCLUDE linkcmds.memory

                ~ sections{

                ~   .text:{

                ~       *(.text)

                ~   }> REGION_TEXT

                ~   …

                ~ }

                `

                ~ MEMORY{

                ~   RAM: ORIGIN=0, LENGTH=4M

                ~   …

                ~ }

                ~ REGION_ALIAS(“REGION_TEXT”, RAM)

                ~ …

            ASSERT(exp, message)

                if(!exp){print(message)}

            EXTERN(symbol symbol …):

                make symbol undefined

            NOCROSSREFS(section1 section2 …)

                function in section1 can’t call function in section2

            symbol:

                operator:

                    =:  declare, transfer 

                        ~ etext = .

                        ! etext can be used in code, with uninitilized global var etext.    

                        ! . can only used on section command

                    +=

                    -=

                    *=

                    /=

                    <<=

                    >>=

                    &=

                    |=

            HIDDEN(symbol):

                ~ HIDDEN(etext = .)

                ! can NOT accessed in other program(not exported)

            PROVIDE(symbol):

                ~ PROVIDE(etext = .)

                # if symbol not defined will defined etext with ., otherwise use original definition

            PROVIDE_HIDDEN(symbol)

            sections:

                ~ sections{

                ~   sections-command

                ~   sections-command

                ~   …

                ~ }

            sections-command:

                entry

                symbol

                output section:

                    section [address] [(type)]: 

                            [AT(lma)] [ALIGIN(section_aligin)] [SUBALIGIN(subsection_aligin)]

                            [constraint] { output-section-command} [>region] [AT>lma_origin] [:phdr :phdr] [=fillexp]

                    VMA:    Virtual Memory Address

                    LMA:    Load Memory Address

                        ! LMA can be defined by AT or AT> command

                    ~ .text (.) :{ *(.text) }

                        section without address can’t be predicted

                    ~ *(EXCLUDE_FILE(*www.o) .ctors)

                    ~ (.text .rodata) vs (.text) *(.rodata) 

                        second description text and rodata will be separated

                    SORT_BY_NAME SORT_BY_ALIGINMENT

                    KEEP(sections)

                    COMMON

                        # common symbol?

                    FILL(value)

                    CREATE_OBJECT_SYMBOLS

                    /DISCARD/: length is zero

                    type:

                        NOLOAD:     will not load into memory

                        DSECT:      will not alloc memory during load

                        COPY

                        INFO

                        OVERLAY

                OVERLAY:

                    will override previous definition in SECTIONS, same as SECTIONS

                MEMORY:

                    ~ MEMORY{

                    ~   name [(attr)]: ORIGIN = origin, LENGTH = len

                    ~ }

                    attr:

                        R W X A I L !

                        R: read only

                        W: write & read

                        X: executable

                        A: allocable

                        I: already initilized

                        L: = I

                        !: NOT

                separated section:

                    ld will guess where these section will be put

                . = .:

                    special usage. ld think you have saved .

                functions:

                    ABSOLUTE(exp)

                    ADDR(section)

                    ALIGIN(aligin)

                    ALIGIN(exp, aligin)

                    ALIGINOF(section)

                    DATA_SEGMENT_ALIGIN(maxpagesize, commonpagesize)

                    DEFINED(symbol)

                    LEGNTH(memory)

                    LOADADDR(section): LMA

                    MAX(exp1, exp2)

                    MIN(exp1, exp2)

                    NEXT(exp)   : nearest not alloc address can be divided by exp

                    ORIGIN(exp) : start address

                    SEGMENT_START(segment, default)

                    SIZEOF(section)

                    SIZEOF_HEADERS

Linux

    GNU ASM:

        fake instruction / command:

            .ascii

            .asciz

            .baligin  byte alignment by 2^power_of_2

            .byte  {, …} insert data to output

            .hword  {, …} 

            .word  {, …} 

            .code  .code 32, .code 16: ARM, Thumb (instruction)

            .else .if .endif .ifdef .ifndef

            .end  EOF

            .macro name {arg1, arg2, …}

            .endm macro end

            .rept 

            .endr loop end

            .equ symbol, value   #define symbol value

            .err error

            .exitm exit macro

            .global symbol       make symbol global

            .include ”

             .req : acc .req r0

            .section  {, ”“} awx

            .set 

            .space {, }

        @ # ; #$

        addr, %rn, [%rn], [%rn, #n], #imm

    led: write register. such as mcu.

u-boot:

    arch/arm/armv7/start.S 

        ! now arch/arm/lib/vector.S

    [todo] boot sequense is IMPORTANT.

        ! something OUT-OF-DATE!

        ! anlysis boot sequense using gnu elftools

        ! anlysis boot sequense using symbol and arm instrution

    CP15 have NO explanation in this book.

        # maybe armv8 user guide?

Bootloader:

    IAP

        # [TODO] Try write it on STM32?

        # why not build IAP using FreeRTOS?

    boot linux:

        bootloader should do these things before booting linux:

            initilize RAM:

                load kernel to RAM to run 

                    ! not SRAM, kernel Image is too big to run in SRAM

            initilize at least one UART port:

                just for debug

            detect CPU Type

                put machine type in R1.

                linux/arch/arm/tools/mach-types

            establish kernel tag list:

                tag list:

                    ATAG_CORE

                    ATAG_MEM

                    ATAG_NONE

                dtb:

                    64bit aligin(????) put in ram

                        ? I have tried not put in 64bit aligin using bootz, but also successed

                    magic number: 0xd00dfeed

                    documention/devicetree/booting-with-out-of.txt

            call kernel image

                put zImage on RAM and execute

        bootloader must disable all DMA devices (?)

            (?) just use dma to load zImage data into RAM. but why can’t?

        r0 = 0

        r1 = mach-types

        r2 = taglist or dtb address

        CPU must in SVC mode and disable irq and fiq.

        Cache and MMU must disabled. Code cache is optional to close.

        Cortex-A must set ARM instruction mode .code 32 / .ARM

        Cortex-M must set Thumb instruction mode .code 16 / .Thumb

Summary:

    what bootloader do?

        initialize watch dog

        initialize clock

        initialize serial

        set sp(r14) and enter svc mode

        initialize ram

        initialize mmc controller

        clear .bss

        prepare to boot linux

        branch to address of linux kernel

    bootloader lifecycle ended