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 繼續執行。由於之後又是一個新的階段,本節暫告一段落。