From f2ff75c0a25eb78b4b86fd96c5f0be9dd327e2d7 Mon Sep 17 00:00:00 2001 From: Graeme Russ Date: Thu, 7 Oct 2010 20:03:33 +1100 Subject: [PATCH] x86: Use loops instead of memcpy/memset in board_init_f Provides a small speed increase and prepares for fully relocatable image. Downside is the TEXT_BASE, bss, load address etc must ALL be aligned on a a 4-byte boundary which is not such a terrible restriction as everything is already 4-byte aligned anyway --- arch/i386/lib/board.c | 47 ++++++++++++++++++++++++++++--------------- board/eNET/u-boot.lds | 3 ++- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/arch/i386/lib/board.c b/arch/i386/lib/board.c index 3e89ef42827..9c2f77fd544 100644 --- a/arch/i386/lib/board.c +++ b/arch/i386/lib/board.c @@ -53,7 +53,7 @@ extern ulong __data_end; extern ulong __rel_dyn_start; extern ulong __rel_dyn_end; extern ulong __bss_start; -extern ulong __bss_size; +extern ulong __bss_end; const char version_string[] = U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")"; @@ -172,18 +172,22 @@ void board_init_f (ulong gdp) { void *text_start = &__text_start; void *data_end = &__data_end; - Elf32_Rel *rel_dyn_start = (Elf32_Rel *)&__rel_dyn_start; - Elf32_Rel *rel_dyn_end = (Elf32_Rel *)&__rel_dyn_end; + void *rel_dyn_start = &__rel_dyn_start; + void *rel_dyn_end = &__rel_dyn_end; void *bss_start = &__bss_start; - ulong bss_size = (ulong)&__bss_size; + void *bss_end = &__bss_end; + + ulong *dst_addr; + ulong *src_addr; + ulong *end_addr; - ulong uboot_size; void *dest_addr; ulong rel_offset; - Elf32_Rel *re; + Elf32_Rel *re_src; + Elf32_Rel *re_end; - uboot_size = (ulong)data_end - (ulong)text_start; - dest_addr = (void *)gdp - (uboot_size + (ulong)bss_size); + /* Calculate destination RAM Address and relocation offset */ + dest_addr = (void *)gdp - (bss_end - text_start); rel_offset = text_start - dest_addr; /* First stage CPU initialization */ @@ -195,18 +199,29 @@ void board_init_f (ulong gdp) hang(); /* Copy U-Boot into RAM */ - memcpy(dest_addr, text_start, uboot_size); + dst_addr = (ulong *)dest_addr; + src_addr = (ulong *)text_start; + end_addr = (ulong *)data_end; + + while (src_addr < end_addr) + *dst_addr++ = *src_addr++; /* Clear BSS */ - memset(bss_start - rel_offset, 0, bss_size); + dst_addr = (ulong *)(bss_start - rel_offset); + end_addr = (ulong *)(bss_end - rel_offset); + + while (dst_addr < end_addr) + *dst_addr++ = 0x00000000; /* Perform relocation adjustments */ - for (re = rel_dyn_start; re < rel_dyn_end; re++) - { - if (re->r_offset >= TEXT_BASE) - if (*(ulong *)re->r_offset >= TEXT_BASE) - *(ulong *)(re->r_offset - rel_offset) -= (Elf32_Addr)rel_offset; - } + re_src = (Elf32_Rel *)rel_dyn_start; + re_end = (Elf32_Rel *)rel_dyn_end; + + do { + if (re_src->r_offset >= TEXT_BASE) + if (*(Elf32_Addr *)(re_src->r_offset - rel_offset) >= TEXT_BASE) + *(Elf32_Addr *)(re_src->r_offset - rel_offset) -= rel_offset; + } while (re_src++ < re_end); ((gd_t *)gdp)->reloc_off = rel_offset; ((gd_t *)gdp)->flags |= GD_FLG_RELOC; diff --git a/board/eNET/u-boot.lds b/board/eNET/u-boot.lds index 3c52010651c..b414079bc14 100644 --- a/board/eNET/u-boot.lds +++ b/board/eNET/u-boot.lds @@ -58,7 +58,8 @@ SECTIONS . = ALIGN(4); __bss_start = ABSOLUTE(.); .bss (NOLOAD) : { *(.bss) } - __bss_size = SIZEOF(.bss); + . = ALIGN(4); + __bss_end = ABSOLUTE(.); . = ALIGN(4); __rel_dyn_start = .;