diff options
Diffstat (limited to 'arch/blackfin/kernel/module.c')
-rw-r--r-- | arch/blackfin/kernel/module.c | 111 |
1 files changed, 60 insertions, 51 deletions
diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c index 50d7fbfe1ce6..2ad805e67afc 100644 --- a/arch/blackfin/kernel/module.c +++ b/arch/blackfin/kernel/module.c | |||
@@ -53,7 +53,7 @@ void module_free(struct module *mod, void *module_region) | |||
53 | 53 | ||
54 | /* Transfer the section to the L1 memory */ | 54 | /* Transfer the section to the L1 memory */ |
55 | int | 55 | int |
56 | module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, | 56 | module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, |
57 | char *secstrings, struct module *mod) | 57 | char *secstrings, struct module *mod) |
58 | { | 58 | { |
59 | /* | 59 | /* |
@@ -64,12 +64,18 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, | |||
64 | * NOTE: this breaks the semantic of mod->arch structure. | 64 | * NOTE: this breaks the semantic of mod->arch structure. |
65 | */ | 65 | */ |
66 | Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum; | 66 | Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum; |
67 | void *dest = NULL; | 67 | void *dest; |
68 | 68 | ||
69 | for (s = sechdrs; s < sechdrs_end; ++s) { | 69 | for (s = sechdrs; s < sechdrs_end; ++s) { |
70 | if ((strcmp(".l1.text", secstrings + s->sh_name) == 0) || | 70 | const char *shname = secstrings + s->sh_name; |
71 | ((strcmp(".text", secstrings + s->sh_name) == 0) && | 71 | |
72 | (hdr->e_flags & EF_BFIN_CODE_IN_L1) && (s->sh_size > 0))) { | 72 | if (s->sh_size == 0) |
73 | continue; | ||
74 | |||
75 | if (!strcmp(".l1.text", shname) || | ||
76 | (!strcmp(".text", shname) && | ||
77 | (hdr->e_flags & EF_BFIN_CODE_IN_L1))) { | ||
78 | |||
73 | dest = l1_inst_sram_alloc(s->sh_size); | 79 | dest = l1_inst_sram_alloc(s->sh_size); |
74 | mod->arch.text_l1 = dest; | 80 | mod->arch.text_l1 = dest; |
75 | if (dest == NULL) { | 81 | if (dest == NULL) { |
@@ -78,12 +84,11 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, | |||
78 | return -1; | 84 | return -1; |
79 | } | 85 | } |
80 | dma_memcpy(dest, (void *)s->sh_addr, s->sh_size); | 86 | dma_memcpy(dest, (void *)s->sh_addr, s->sh_size); |
81 | s->sh_flags &= ~SHF_ALLOC; | 87 | |
82 | s->sh_addr = (unsigned long)dest; | 88 | } else if (!strcmp(".l1.data", shname) || |
83 | } | 89 | (!strcmp(".data", shname) && |
84 | if ((strcmp(".l1.data", secstrings + s->sh_name) == 0) || | 90 | (hdr->e_flags & EF_BFIN_DATA_IN_L1))) { |
85 | ((strcmp(".data", secstrings + s->sh_name) == 0) && | 91 | |
86 | (hdr->e_flags & EF_BFIN_DATA_IN_L1) && (s->sh_size > 0))) { | ||
87 | dest = l1_data_sram_alloc(s->sh_size); | 92 | dest = l1_data_sram_alloc(s->sh_size); |
88 | mod->arch.data_a_l1 = dest; | 93 | mod->arch.data_a_l1 = dest; |
89 | if (dest == NULL) { | 94 | if (dest == NULL) { |
@@ -92,12 +97,11 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, | |||
92 | return -1; | 97 | return -1; |
93 | } | 98 | } |
94 | memcpy(dest, (void *)s->sh_addr, s->sh_size); | 99 | memcpy(dest, (void *)s->sh_addr, s->sh_size); |
95 | s->sh_flags &= ~SHF_ALLOC; | 100 | |
96 | s->sh_addr = (unsigned long)dest; | 101 | } else if (!strcmp(".l1.bss", shname) || |
97 | } | 102 | (!strcmp(".bss", shname) && |
98 | if (strcmp(".l1.bss", secstrings + s->sh_name) == 0 || | 103 | (hdr->e_flags & EF_BFIN_DATA_IN_L1))) { |
99 | ((strcmp(".bss", secstrings + s->sh_name) == 0) && | 104 | |
100 | (hdr->e_flags & EF_BFIN_DATA_IN_L1) && (s->sh_size > 0))) { | ||
101 | dest = l1_data_sram_zalloc(s->sh_size); | 105 | dest = l1_data_sram_zalloc(s->sh_size); |
102 | mod->arch.bss_a_l1 = dest; | 106 | mod->arch.bss_a_l1 = dest; |
103 | if (dest == NULL) { | 107 | if (dest == NULL) { |
@@ -105,10 +109,9 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, | |||
105 | mod->name); | 109 | mod->name); |
106 | return -1; | 110 | return -1; |
107 | } | 111 | } |
108 | s->sh_flags &= ~SHF_ALLOC; | 112 | |
109 | s->sh_addr = (unsigned long)dest; | 113 | } else if (!strcmp(".l1.data.B", shname)) { |
110 | } | 114 | |
111 | if (strcmp(".l1.data.B", secstrings + s->sh_name) == 0) { | ||
112 | dest = l1_data_B_sram_alloc(s->sh_size); | 115 | dest = l1_data_B_sram_alloc(s->sh_size); |
113 | mod->arch.data_b_l1 = dest; | 116 | mod->arch.data_b_l1 = dest; |
114 | if (dest == NULL) { | 117 | if (dest == NULL) { |
@@ -117,10 +120,9 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, | |||
117 | return -1; | 120 | return -1; |
118 | } | 121 | } |
119 | memcpy(dest, (void *)s->sh_addr, s->sh_size); | 122 | memcpy(dest, (void *)s->sh_addr, s->sh_size); |
120 | s->sh_flags &= ~SHF_ALLOC; | 123 | |
121 | s->sh_addr = (unsigned long)dest; | 124 | } else if (!strcmp(".l1.bss.B", shname)) { |
122 | } | 125 | |
123 | if (strcmp(".l1.bss.B", secstrings + s->sh_name) == 0) { | ||
124 | dest = l1_data_B_sram_alloc(s->sh_size); | 126 | dest = l1_data_B_sram_alloc(s->sh_size); |
125 | mod->arch.bss_b_l1 = dest; | 127 | mod->arch.bss_b_l1 = dest; |
126 | if (dest == NULL) { | 128 | if (dest == NULL) { |
@@ -129,12 +131,11 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, | |||
129 | return -1; | 131 | return -1; |
130 | } | 132 | } |
131 | memset(dest, 0, s->sh_size); | 133 | memset(dest, 0, s->sh_size); |
132 | s->sh_flags &= ~SHF_ALLOC; | 134 | |
133 | s->sh_addr = (unsigned long)dest; | 135 | } else if (!strcmp(".l2.text", shname) || |
134 | } | 136 | (!strcmp(".text", shname) && |
135 | if ((strcmp(".l2.text", secstrings + s->sh_name) == 0) || | 137 | (hdr->e_flags & EF_BFIN_CODE_IN_L2))) { |
136 | ((strcmp(".text", secstrings + s->sh_name) == 0) && | 138 | |
137 | (hdr->e_flags & EF_BFIN_CODE_IN_L2) && (s->sh_size > 0))) { | ||
138 | dest = l2_sram_alloc(s->sh_size); | 139 | dest = l2_sram_alloc(s->sh_size); |
139 | mod->arch.text_l2 = dest; | 140 | mod->arch.text_l2 = dest; |
140 | if (dest == NULL) { | 141 | if (dest == NULL) { |
@@ -143,12 +144,11 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, | |||
143 | return -1; | 144 | return -1; |
144 | } | 145 | } |
145 | memcpy(dest, (void *)s->sh_addr, s->sh_size); | 146 | memcpy(dest, (void *)s->sh_addr, s->sh_size); |
146 | s->sh_flags &= ~SHF_ALLOC; | 147 | |
147 | s->sh_addr = (unsigned long)dest; | 148 | } else if (!strcmp(".l2.data", shname) || |
148 | } | 149 | (!strcmp(".data", shname) && |
149 | if ((strcmp(".l2.data", secstrings + s->sh_name) == 0) || | 150 | (hdr->e_flags & EF_BFIN_DATA_IN_L2))) { |
150 | ((strcmp(".data", secstrings + s->sh_name) == 0) && | 151 | |
151 | (hdr->e_flags & EF_BFIN_DATA_IN_L2) && (s->sh_size > 0))) { | ||
152 | dest = l2_sram_alloc(s->sh_size); | 152 | dest = l2_sram_alloc(s->sh_size); |
153 | mod->arch.data_l2 = dest; | 153 | mod->arch.data_l2 = dest; |
154 | if (dest == NULL) { | 154 | if (dest == NULL) { |
@@ -157,12 +157,11 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, | |||
157 | return -1; | 157 | return -1; |
158 | } | 158 | } |
159 | memcpy(dest, (void *)s->sh_addr, s->sh_size); | 159 | memcpy(dest, (void *)s->sh_addr, s->sh_size); |
160 | s->sh_flags &= ~SHF_ALLOC; | 160 | |
161 | s->sh_addr = (unsigned long)dest; | 161 | } else if (!strcmp(".l2.bss", shname) || |
162 | } | 162 | (!strcmp(".bss", shname) && |
163 | if (strcmp(".l2.bss", secstrings + s->sh_name) == 0 || | 163 | (hdr->e_flags & EF_BFIN_DATA_IN_L2))) { |
164 | ((strcmp(".bss", secstrings + s->sh_name) == 0) && | 164 | |
165 | (hdr->e_flags & EF_BFIN_DATA_IN_L2) && (s->sh_size > 0))) { | ||
166 | dest = l2_sram_zalloc(s->sh_size); | 165 | dest = l2_sram_zalloc(s->sh_size); |
167 | mod->arch.bss_l2 = dest; | 166 | mod->arch.bss_l2 = dest; |
168 | if (dest == NULL) { | 167 | if (dest == NULL) { |
@@ -170,10 +169,14 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs, | |||
170 | mod->name); | 169 | mod->name); |
171 | return -1; | 170 | return -1; |
172 | } | 171 | } |
173 | s->sh_flags &= ~SHF_ALLOC; | 172 | |
174 | s->sh_addr = (unsigned long)dest; | 173 | } else |
175 | } | 174 | continue; |
175 | |||
176 | s->sh_flags &= ~SHF_ALLOC; | ||
177 | s->sh_addr = (unsigned long)dest; | ||
176 | } | 178 | } |
179 | |||
177 | return 0; | 180 | return 0; |
178 | } | 181 | } |
179 | 182 | ||
@@ -295,22 +298,28 @@ module_finalize(const Elf_Ehdr * hdr, | |||
295 | for (i = 1; i < hdr->e_shnum; i++) { | 298 | for (i = 1; i < hdr->e_shnum; i++) { |
296 | const char *strtab = (char *)sechdrs[strindex].sh_addr; | 299 | const char *strtab = (char *)sechdrs[strindex].sh_addr; |
297 | unsigned int info = sechdrs[i].sh_info; | 300 | unsigned int info = sechdrs[i].sh_info; |
301 | const char *shname = secstrings + sechdrs[i].sh_name; | ||
298 | 302 | ||
299 | /* Not a valid relocation section? */ | 303 | /* Not a valid relocation section? */ |
300 | if (info >= hdr->e_shnum) | 304 | if (info >= hdr->e_shnum) |
301 | continue; | 305 | continue; |
302 | 306 | ||
303 | if ((sechdrs[i].sh_type == SHT_RELA) && | 307 | /* Only support RELA relocation types */ |
304 | ((strcmp(".rela.l2.text", secstrings + sechdrs[i].sh_name) == 0) || | 308 | if (sechdrs[i].sh_type != SHT_RELA) |
305 | (strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) || | 309 | continue; |
306 | ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) && | 310 | |
307 | (hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) { | 311 | if (!strcmp(".rela.l2.text", shname) || |
312 | !strcmp(".rela.l1.text", shname) || | ||
313 | (!strcmp(".rela.text", shname) && | ||
314 | (hdr->e_flags & (EF_BFIN_CODE_IN_L1 | EF_BFIN_CODE_IN_L2)))) { | ||
315 | |||
308 | err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab, | 316 | err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab, |
309 | symindex, i, mod); | 317 | symindex, i, mod); |
310 | if (err < 0) | 318 | if (err < 0) |
311 | return -ENOEXEC; | 319 | return -ENOEXEC; |
312 | } | 320 | } |
313 | } | 321 | } |
322 | |||
314 | return 0; | 323 | return 0; |
315 | } | 324 | } |
316 | 325 | ||