1. 程式人生 > >NanoPC-T2 Uboot啟動過程分析

NanoPC-T2 Uboot啟動過程分析

在繼續分析之前,先回顧一下當前相關暫存器的值、記憶體空間的使用情況和相關變數的值的情況。


Registers:

r0 = 0

r9 = 0x42BF_FF60 @ &gd

r13 = &( bl mmu_turn_on ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S

sp = 0x42BF_FF60

lr = &( bl board_init_f ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S

RAM:

0xC000_0000

 -

0x5000_0000(RAM_TOP)

 -

0x4FFE_F800

 UBOOT(Reserve 478
K) 0x4FF7_8000 - 0x4FFF_4000 TLB table 0x4FFF_0000 - 0x4DF9_8000 malloc(Reserve 32768K) 0x4DF7_8000 Board Info(Reserve 80B) = gd->bd 0x4DF7_7FB0 New GD 0x4DF7_7F10 IRQ 0x4DF7_7F00(IRQ_SP) - 0x4DF7_7EF0(START_ADDR_SP) UBOOT 0x42C0_0000 GD 0x42BF_FF60 UBoot-Stack 0x4000_0000

gd值:


bd_t *bd

{

unsigned long
bi_memstart = 0 phys_size_t bi_memsize = 0 unsigned long bi_flashstart = 0 unsigned long bi_flashsize = 0 unsigned long bi_flashoffset = 0 unsigned long bi_sramstart = 0 unsigned long bi_sramsize = 0 unsigned long bi_bootflags = 0 unsigned long bi_ip_addr = 0 unsigned char bi_enetaddr[6] = 0 unsigned
short bi_ethspeed = 0 unsigned long bi_intfreq = 0 unsigned long bi_busfreq = 0 ulong bi_arch_number = 0 ulong bi_boot_params = 0 struct bi_dram[1] { ulong start = 0 ulong size = 0 } } unsigned long flags = 0 unsigned int baudrate = 115200 unsigned long cpu_clk = 0 unsigned long bus_clk = 0 unsigned long pci_clk = 0 unsigned long mem_clk = 0 unsigned long have_console = 1 unsigned long env_addr = &default_environment[0] unsigned long env_valid = 1 unsigned long ram_top = 0x5000_0000 unsigned long relocaddr = 0x4FF7_8000 phys_size_t ram_size = 0x1000_0000 unsigned long mon_len = 0x0007_7988 unsigned long irq_sp = 0x4DF7_7F00 unsigned long start_addr_sp = 0x4df7_7EF0 unsigned long reloc_off = 0 struct global_data *new_gd = 0x4df7_7f10 const void *fdt_blob = 0 void *new_fdt = 0 unsigned long fdt_size = 0 void **jt = 0 char env_buf[32] = 0 unsigned long timebase_h = 0 unsigned long timebase_l = 0 struct arch_global_data arch { unsigned long timer_rate_hz = 0 unsigned long tbu = 0 unsigned long tbl = 0 unsigned long lastinc = 0 unsigned long long timer_reset_value = 0 unsigned long tlb_addr = 0x4fff_0000 unsigned long tlb_size = 0x0000_4000 }

現在繼續分析位於 \/uboot-root\/common\/board_f.c 中的 init_sequence_f[] 中的 setup_dram_config() 。這個函式呼叫了位於 \/uboot-root\/arch\/arm\/cpu\/slsiap\/s5p4418\/cpu.c 中的 dram_init_banksize()。主要更新了 gd 中的成員,與DRAM、架構號和啟動引數位置有關。更新後的內容如下:


bd_t *bd

{

unsigned long bi_memstart = 0

phys_size_t bi_memsize = 0

unsigned long bi_flashstart = 0

unsigned long bi_flashsize = 0

unsigned long bi_flashoffset = 0

unsigned long bi_sramstart = 0

unsigned long bi_sramsize = 0

unsigned long bi_bootflags = 0

unsigned long bi_ip_addr = 0

unsigned char bi_enetaddr[6] = 0

unsigned short bi_ethspeed = 0

unsigned long bi_intfreq = 0

unsigned long bi_busfreq = 0

ulong bi_arch_number = 4330

ulong bi_boot_params = 0x4000_0100

struct bi_dram[1]

{

ulong start = 0x4000_0000

ulong size = 0x4000_0000

}

}

unsigned long flags = 0

unsigned int baudrate = 115200

unsigned long cpu_clk = 0

unsigned long bus_clk = 0

unsigned long pci_clk = 0

unsigned long mem_clk = 0

unsigned long have_console = 1

unsigned long env_addr = &default_environment[0]

unsigned long env_valid = 1

unsigned long ram_top = 0x5000_0000

unsigned long relocaddr = 0x4FF7_8000

phys_size_t ram_size = 0x1000_0000

unsigned long mon_len = 0x0007_7988

unsigned long irq_sp = 0x4DF7_7F00

unsigned long start_addr_sp = 0x4df7_7EF0

unsigned long reloc_off = 0

struct global_data *new_gd = 0x4df7_7f10

const void *fdt_blob = 0

void *new_fdt = 0

unsigned long fdt_size = 0

void **jt = 0

char env_buf[32] = 0

unsigned long timebase_h = 0

unsigned long timebase_l = 0

struct arch_global_data arch

{

unsigned long timer_rate_hz = 0

unsigned long tbu = 0

unsigned long tbl = 0

unsigned long lastinc = 0

unsigned long long timer_reset_value = 0

unsigned long tlb_addr = 0x4fff_0000

unsigned long tlb_size = 0x0000_4000

}

接下來呼叫的是 show_dram_config()。這裡主要是輸出DRAM的資訊,因此不詳細展開。

接下來呼叫的是 display_new_sp()。這裡主要是輸出棧的資訊,因此忽略。

接下來呼叫的是 reloc_fdt()。由於gd->new_fdt=0,因此這裡沒有動作,忽略。

接下來呼叫的是 setup_reloc()。這裡是一個關鍵的地方。首先先更新gd->reloc_off,然後將整個gd的內容複製到之前保留的gd->new_gd的地址上,即0x4df7_7f10。以下是更新後的gd內容:


bd_t *bd

{

unsigned long bi_memstart = 0

phys_size_t bi_memsize = 0

unsigned long bi_flashstart = 0

unsigned long bi_flashsize = 0

unsigned long bi_flashoffset = 0

unsigned long bi_sramstart = 0

unsigned long bi_sramsize = 0

unsigned long bi_bootflags = 0

unsigned long bi_ip_addr = 0

unsigned char bi_enetaddr[6] = 0

unsigned short bi_ethspeed = 0

unsigned long bi_intfreq = 0

unsigned long bi_busfreq = 0

ulong bi_arch_number = 4330

ulong bi_boot_params = 0x4000_0100

struct bi_dram[1]

{

ulong start = 0x4000_0000

ulong size = 0x4000_0000

}

}

unsigned long flags = 0

unsigned int baudrate = 115200

unsigned long cpu_clk = 0

unsigned long bus_clk = 0

unsigned long pci_clk = 0

unsigned long mem_clk = 0

unsigned long have_console = 1

unsigned long env_addr = &default_environment[0]

unsigned long env_valid = 1

unsigned long ram_top = 0x5000_0000

unsigned long relocaddr = 0x4ff7_8000

phys_size_t ram_size = 0x1000_0000

unsigned long mon_len = 0x0007_7988

unsigned long irq_sp = 0x4DF7_7F00

unsigned long start_addr_sp = 0x4df7_7EF0

unsigned long reloc_off = 0x0D37_8000

struct global_data *new_gd = 0x4df7_7f10

const void *fdt_blob = 0

void *new_fdt = 0

unsigned long fdt_size = 0

void **jt = 0

char env_buf[32] = 0

unsigned long timebase_h = 0

unsigned long timebase_l = 0

struct arch_global_data arch

{

unsigned long timer_rate_hz = 0

unsigned long tbu = 0

unsigned long tbl = 0

unsigned long lastinc = 0

unsigned long long timer_reset_value = 0

unsigned long tlb_addr = 0x4fff_0000

unsigned long tlb_size = 0x0000_4000

}

到這裡,init_sequence_f[]裡的所有函式全部呼叫完畢。回憶相關的暫存器值:


r0 = 0

r9 = 0x42BF_FF60 @ &gd

r13 = &( bl mmu_turn_on ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S

sp = 0x42BF_FF60

lr = &( bl board_init_f ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S

根據 lr 的值,UBoot重新回到 \/uboot-root\/arch\/arm\/cpu\/slsiap\/s5p4418\/start.S 繼續執行,其程式碼如下:


    mov sp, r9 /* SP is GD's base address */

    bic sp, sp, #7 /* 8-byte alignment for ABI compliance */    

    sub sp, #GENERATED_BD_INFO_SIZE /* allocate one BD above SP */

    bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

    mov r0, r9 /* gd_t *gd */

    ldr r1, TEXT_BASE /* ulong text */

    mov r2, sp /* ulong sp */

    bl gdt_reset

以上的程式碼更新了一些暫存器,併為呼叫 gdt_reset() 準備引數。因此,在呼叫最後一條指令時,相關暫存器的值和記憶體使用空間如下:


r0 = 0x42BF_FF60 @ &gd

r1 = 0x42C0_0000

r2 = 0x42BF_FF10 @ &sp

r9 = 0x42BF_FF60 @ &gd

r13 = &( bl mmu_turn_on ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S

sp = 0x42BF_FF10

lr = &( bl gdt_reset ) @ /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S

RAM:

0xC000_0000

 -
0x5000_0000(RAM_TOP)

 -
0x4FFE_F800

 UBOOT(Reserve 478K)

0x4FF7_8000

 -
0x4FFF_4000

 TLB table

0x4FFF_0000

 -
0x4DF9_8000

 malloc(Reserve 32768K)

0x4DF7_8000

 Board Info(Reserve 80B) = gd->bd

0x4DF7_7FB0

 New GD

0x4DF7_7F10

 IRQ

0x4DF7_7F00(IRQ_SP)

 -
0x4DF7_7EF0(START_ADDR_SP)

 UBOOT

0x42C0_0000

 GD

0x42BF_FF60

 BD Info

0x42BF_FF10

 UBoot-Stack

0x4000_0000

gdt_reset()位於 \/uboot-root\/arch\/arm\/cpu\/slsiap\/s5p4418\/cpu.c 中。其程式碼如下:


void gdt_reset(gd_t *gd, ulong text, ulong sp)

{

 ulong text_start, text_end, heap_end;

 ulong bd;

 /* for smp cores */

 global_descriptor = gd;

 /* reconfig stack info */

 gd->relocaddr = text;

 gd->start_addr_sp = sp;

 gd->reloc_off = 0;

 /* copy bd info */

 bd = (unsigned int)gd - sizeof(bd_t);

 memcpy((void *)bd, (void *)gd->bd, sizeof(bd_t));

 /* reset gd->bd */

 gd->bd = (bd_t *)bd;

 /* prevent dataabort, when access enva_addr + data (0x04) */

 gd->env_addr = (ulong)default_environment;

 /* get cpu info */

 text_start = (unsigned int)(gd->relocaddr);

 text_end = (unsigned int)(gd->relocaddr + _bss_end_ofs);

 heap_end = CONFIG_SYS_MALLOC_END;

 /* refer initr_malloc (common/board_r.c) */

 gd->relocaddr = heap_end;

 flush_dcache_all();

 ulong pc;

 asm("mov %0, pc":"=r" (pc));

 asm("mov %0, sp":"=r" (sp));

 printf("Heap = 0x%08lx~0x%08lx\n", heap_end-TOTAL_MALLOC_LEN, heap_end);

 printf("Code = 0x%08lx~0x%08lx\n", text_start, text_end);

 printf("GLD = 0x%08lx\n", (ulong)gd);

 printf("GLBD = 0x%08lx\n", (ulong)gd->bd);

 printf("SP = 0x%08lx,0x%08lx(CURR)\n", gd->start_addr_sp, sp);

 printf("PC = 0x%08lx\n", pc);

 printf("TAGS = 0x%08lx \n", gd->bd->bi_boot_params);

 ulong page_tlb = (text_end & 0xffff0000) + 0x10000;

 printf("PAGE = 0x%08lx~0x%08lx\n", page_tlb, page_tlb + 0xc000 );

 printf("MACH = [%ld] \n", gd->bd->bi_arch_number);

 printf("VER = %u \n", nxp_cpu_version());

 printf("BOARD= [%s] \n", CONFIG_SYS_BOARD);

}

這裡首先先更新gd裡的relocaddr、start_addr_sp和reloc_off。接下來將原本儲存在gd->bd中的內容複製到0x42BF_FF10開始的地方,即記憶體空間使用表中的BD Info的位置,同時重新更新gd->bd指向的位置。此時gd的內容如下:


bd_t *bd = 0x42BF_FF10

{

unsigned long bi_memstart = 0

phys_size_t bi_memsize = 0

unsigned long bi_flashstart = 0

unsigned long bi_flashsize = 0

unsigned long bi_flashoffset = 0

unsigned long bi_sramstart = 0

unsigned long bi_sramsize = 0

unsigned long bi_bootflags = 0

unsigned long bi_ip_addr = 0

unsigned char bi_enetaddr[6] = 0

unsigned short bi_ethspeed = 0

unsigned long bi_intfreq = 0

unsigned long bi_busfreq = 0

ulong bi_arch_number = 4330

ulong bi_boot_params = 0x4000_0100

struct bi_dram[1]

{

ulong start = 0x4000_0000

ulong size = 0x4000_0000

}

}

unsigned long flags = 0

unsigned int baudrate = 115200

unsigned long cpu_clk = 0

unsigned long bus_clk = 0

unsigned long pci_clk = 0

unsigned long mem_clk = 0

unsigned long have_console = 1

unsigned long env_addr = &default_environment[0]

unsigned long env_valid = 1

unsigned long ram_top = 0x5000_0000

unsigned long relocaddr = 0x4500_0000

phys_size_t ram_size = 0x1000_0000

unsigned long mon_len = 0x0007_7988

unsigned long irq_sp = 0x4DF7_7F00

unsigned long start_addr_sp = 0x42BF_FF10

unsigned long reloc_off = 0

struct global_data *new_gd = 0x4df7_7f10

const void *fdt_blob = 0

void *new_fdt = 0

unsigned long fdt_size = 0

void **jt = 0

char env_buf[32] = 0

unsigned long timebase_h = 0

unsigned long timebase_l = 0

struct arch_global_data arch

{

unsigned long timer_rate_hz = 0

unsigned long tbu = 0

unsigned long tbl = 0

unsigned long lastinc = 0

unsigned long long timer_reset_value = 0

unsigned long tlb_addr = 0x4fff_0000

unsigned long tlb_size = 0x0000_4000

}

接下來是重新整理dcache和輸出記憶體空間表:


RAM:

0xC000_0000

 -

0x5000_0000(RAM_TOP)

 -

0x4FFE_F800

 UBOOT(Reserve 478K)

0x4FF7_8000

 -

0x4FFF_4000

 TLB table

0x4FFF_0000

 -

0x4DF9_8000

 malloc(Reserve 32768K)

0x4DF7_8000

 Board Info(Reserve 80B) = gd->bd

0x4DF7_7FB0

 New GD

0x4DF7_7F10

 IRQ

0x4DF7_7F00(IRQ_SP)

 -

0x4DF7_7EF0

 -

0x4500_0000

 Heap

0x4300_0000

 -

0x42C8_C000

 Page

0x42C8_0000

 -

0x42C7_7988

 UBOOT

0x42C0_0000

 GD

0x42BF_FEB8

 BD Info

0x42BF_FE68(START_ADDR_SP)

 UBoot-Stack

0x4000_0000

接下來UBoot又返回 /uboot-root/arch/arm/cpu/slsiap/s5p4418/start.S 繼續執行。由於之後又是一個新的階段,本節暫告一段落。