diff options
-rw-r--r-- | kernel/kexec_file.c | 34 |
1 files changed, 12 insertions, 22 deletions
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 6f0ec9f2e5c1..7b63de8a89b6 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c | |||
@@ -785,12 +785,8 @@ out: | |||
785 | static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi, | 785 | static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi, |
786 | struct kexec_buf *kbuf) | 786 | struct kexec_buf *kbuf) |
787 | { | 787 | { |
788 | unsigned long curr_load_addr; | ||
789 | unsigned long load_addr; | ||
790 | unsigned long bss_addr; | 788 | unsigned long bss_addr; |
791 | unsigned long offset; | 789 | unsigned long offset; |
792 | unsigned char *buf_addr; | ||
793 | unsigned char *src; | ||
794 | Elf_Shdr *sechdrs; | 790 | Elf_Shdr *sechdrs; |
795 | int i; | 791 | int i; |
796 | 792 | ||
@@ -823,20 +819,18 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi, | |||
823 | sechdrs[i].sh_offset; | 819 | sechdrs[i].sh_offset; |
824 | } | 820 | } |
825 | 821 | ||
826 | /* Load SHF_ALLOC sections */ | 822 | offset = 0; |
827 | buf_addr = kbuf->buffer; | 823 | bss_addr = kbuf->mem + kbuf->bufsz; |
828 | load_addr = curr_load_addr = kbuf->mem; | ||
829 | bss_addr = load_addr + kbuf->bufsz; | ||
830 | kbuf->image->start = pi->ehdr->e_entry; | 824 | kbuf->image->start = pi->ehdr->e_entry; |
831 | 825 | ||
832 | for (i = 0; i < pi->ehdr->e_shnum; i++) { | 826 | for (i = 0; i < pi->ehdr->e_shnum; i++) { |
833 | unsigned long align; | 827 | unsigned long align; |
828 | void *src, *dst; | ||
834 | 829 | ||
835 | if (!(sechdrs[i].sh_flags & SHF_ALLOC)) | 830 | if (!(sechdrs[i].sh_flags & SHF_ALLOC)) |
836 | continue; | 831 | continue; |
837 | 832 | ||
838 | align = sechdrs[i].sh_addralign; | 833 | align = sechdrs[i].sh_addralign; |
839 | |||
840 | if (sechdrs[i].sh_type == SHT_NOBITS) { | 834 | if (sechdrs[i].sh_type == SHT_NOBITS) { |
841 | bss_addr = ALIGN(bss_addr, align); | 835 | bss_addr = ALIGN(bss_addr, align); |
842 | sechdrs[i].sh_addr = bss_addr; | 836 | sechdrs[i].sh_addr = bss_addr; |
@@ -844,31 +838,27 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi, | |||
844 | continue; | 838 | continue; |
845 | } | 839 | } |
846 | 840 | ||
847 | curr_load_addr = ALIGN(curr_load_addr, align); | 841 | offset = ALIGN(offset, align); |
848 | offset = curr_load_addr - load_addr; | ||
849 | /* We already modifed ->sh_offset to keep src addr */ | ||
850 | src = (char *)sechdrs[i].sh_offset; | ||
851 | memcpy(buf_addr + offset, src, sechdrs[i].sh_size); | ||
852 | |||
853 | if (sechdrs[i].sh_flags & SHF_EXECINSTR && | 842 | if (sechdrs[i].sh_flags & SHF_EXECINSTR && |
854 | pi->ehdr->e_entry >= sechdrs[i].sh_addr && | 843 | pi->ehdr->e_entry >= sechdrs[i].sh_addr && |
855 | pi->ehdr->e_entry < (sechdrs[i].sh_addr | 844 | pi->ehdr->e_entry < (sechdrs[i].sh_addr |
856 | + sechdrs[i].sh_size)) { | 845 | + sechdrs[i].sh_size)) { |
857 | kbuf->image->start -= sechdrs[i].sh_addr; | 846 | kbuf->image->start -= sechdrs[i].sh_addr; |
858 | kbuf->image->start += curr_load_addr; | 847 | kbuf->image->start += kbuf->mem + offset; |
859 | } | 848 | } |
860 | 849 | ||
861 | /* Store load address and source address of section */ | 850 | src = (void *)sechdrs[i].sh_offset; |
862 | sechdrs[i].sh_addr = curr_load_addr; | 851 | dst = pi->purgatory_buf + offset; |
852 | memcpy(dst, src, sechdrs[i].sh_size); | ||
853 | |||
854 | sechdrs[i].sh_addr = kbuf->mem + offset; | ||
863 | 855 | ||
864 | /* | 856 | /* |
865 | * This section got copied to temporary buffer. Update | 857 | * This section got copied to temporary buffer. Update |
866 | * ->sh_offset accordingly. | 858 | * ->sh_offset accordingly. |
867 | */ | 859 | */ |
868 | sechdrs[i].sh_offset = (unsigned long)(buf_addr + offset); | 860 | sechdrs[i].sh_offset = (unsigned long)dst; |
869 | 861 | offset += sechdrs[i].sh_size; | |
870 | /* Advance to the next address */ | ||
871 | curr_load_addr += sechdrs[i].sh_size; | ||
872 | } | 862 | } |
873 | 863 | ||
874 | return 0; | 864 | return 0; |