relocate.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  2. * (C) Copyright 2008-2011
  3. * Graeme Russ, <graeme.russ@gmail.com>
  4. *
  5. * (C) Copyright 2002
  6. * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
  7. *
  8. * (C) Copyright 2002
  9. * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
  10. *
  11. * (C) Copyright 2002
  12. * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  13. * Marius Groeger <mgroeger@sysgo.de>
  14. *
  15. * SPDX-License-Identifier: GPL-2.0+
  16. */
  17. #include <common.h>
  18. #include <inttypes.h>
  19. #include <asm/u-boot-x86.h>
  20. #include <asm/relocate.h>
  21. #include <asm/sections.h>
  22. #include <elf.h>
  23. DECLARE_GLOBAL_DATA_PTR;
  24. int copy_uboot_to_ram(void)
  25. {
  26. size_t len = (size_t)&__data_end - (size_t)&__text_start;
  27. if (gd->flags & GD_FLG_SKIP_RELOC)
  28. return 0;
  29. memcpy((void *)gd->relocaddr, (void *)&__text_start, len);
  30. return 0;
  31. }
  32. int clear_bss(void)
  33. {
  34. ulong dst_addr = (ulong)&__bss_start + gd->reloc_off;
  35. size_t len = (size_t)&__bss_end - (size_t)&__bss_start;
  36. if (gd->flags & GD_FLG_SKIP_RELOC)
  37. return 0;
  38. memset((void *)dst_addr, 0x00, len);
  39. return 0;
  40. }
  41. /*
  42. * This function has more error checking than you might expect. Please see
  43. * the commit message for more informaiton.
  44. */
  45. int do_elf_reloc_fixups(void)
  46. {
  47. Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start);
  48. Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end);
  49. Elf32_Addr *offset_ptr_rom, *last_offset = NULL;
  50. Elf32_Addr *offset_ptr_ram;
  51. unsigned int text_base = 0;
  52. /* The size of the region of u-boot that runs out of RAM. */
  53. uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start;
  54. if (gd->flags & GD_FLG_SKIP_RELOC)
  55. return 0;
  56. if (re_src == re_end)
  57. panic("No relocation data");
  58. #ifdef CONFIG_SYS_TEXT_BASE
  59. text_base = CONFIG_SYS_TEXT_BASE;
  60. #else
  61. panic("No CONFIG_SYS_TEXT_BASE");
  62. #endif
  63. do {
  64. /* Get the location from the relocation entry */
  65. offset_ptr_rom = (Elf32_Addr *)re_src->r_offset;
  66. /* Check that the location of the relocation is in .text */
  67. if (offset_ptr_rom >= (Elf32_Addr *)text_base &&
  68. offset_ptr_rom > last_offset) {
  69. /* Switch to the in-RAM version */
  70. offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom +
  71. gd->reloc_off);
  72. /* Check that the target points into .text */
  73. if (*offset_ptr_ram >= text_base &&
  74. *offset_ptr_ram <= text_base + size) {
  75. *offset_ptr_ram += gd->reloc_off;
  76. } else {
  77. debug(" %p: rom reloc %x, ram %p, value %x,"
  78. " limit %" PRIXPTR "\n", re_src,
  79. re_src->r_offset, offset_ptr_ram,
  80. *offset_ptr_ram,
  81. text_base + size);
  82. }
  83. } else {
  84. debug(" %p: rom reloc %x, last %p\n", re_src,
  85. re_src->r_offset, last_offset);
  86. }
  87. last_offset = offset_ptr_rom;
  88. } while (++re_src < re_end);
  89. return 0;
  90. }