23 #define MAX_RELOS_PER_PASS 4
30 static int priv_tramp_sect_tgt_alloc(
struct dload_state *dlthis)
41 sect_info->
name = dlthis->
tramp.final_string_table;
42 sect_info->
size = dlthis->
tramp.tramp_sect_next_addr;
55 dload_error(dlthis,
"Failed to allocate target memory for"
86 static void priv_tramp_sym_gen_name(
u32 value,
char *
dst)
90 char *dst_local =
dst;
99 *dst_local = *(prefix +
i);
104 for (i = 0; i <
sizeof(
value); i++) {
106 tmp = *(((
u8 *) &value) + (
sizeof(
value) - 1) -
i);
107 *dst_local = priv_h2a((tmp & 0xF0) >> 4);
109 *dst_local = priv_h2a(tmp & 0x0F);
112 tmp = *(((
u8 *) &value) +
i);
113 *dst_local = priv_h2a((tmp & 0xF0) >> 4);
115 *dst_local = priv_h2a(tmp & 0x0F);
144 if (new_string !=
NULL) {
147 for (i = 0; i < (
sizeof(
struct tramp_string) + str_len + 1);
149 *((
u8 *) new_string + i) = 0;
153 new_string->
index = dlthis->
tramp.tramp_string_next_index;
154 dlthis->
tramp.tramp_string_next_index++;
155 dlthis->
tramp.tramp_string_size += str_len + 1;
159 dlthis->
tramp.string_head = new_string;
161 dlthis->
tramp.string_tail->next = new_string;
163 dlthis->
tramp.string_tail = new_string;
166 for (i = 0; i < str_len; i++)
167 new_string->
str[i] = str[i];
186 for (cur_str = dlthis->
tramp.string_head;
187 (ret_val ==
NULL) && (cur_str !=
NULL); cur_str = cur_str->
next) {
194 for (i = 0; i < str_len; i++) {
198 if (str[i] != cur_str->
str[i])
215 static int priv_string_tbl_finalize(
struct dload_state *dlthis)
225 dlthis->
tramp.final_string_table =
226 (
char *)dlthis->
mysym->dload_allocate(dlthis->
mysym,
229 if (dlthis->
tramp.final_string_table !=
NULL) {
232 cur_loc = dlthis->
tramp.final_string_table;
233 cur_string = dlthis->
tramp.string_head;
234 while (cur_string !=
NULL) {
236 dlthis->
tramp.string_head = cur_string->
next;
237 if (dlthis->
tramp.string_tail == cur_string)
241 for (tmp = cur_string->
str;
242 *tmp !=
'\0'; tmp++, cur_loc++)
251 dlthis->
mysym->dload_deallocate(dlthis->
mysym,
255 cur_string = dlthis->
tramp.string_head;
261 dload_error(dlthis,
"Failed to allocate trampoline "
280 if (dlthis->
tramp.tramp_sect_next_addr == 0) {
282 "dynamic TRAMPOLINE section for module %s",
287 ret_val = dlthis->
tramp.tramp_sect_next_addr;
288 dlthis->
tramp.tramp_sect_next_addr += tramp_size;
310 if (new_sym !=
NULL) {
311 for (i = 0; i !=
sizeof(
struct tramp_sym); i++)
312 *((
char *)new_sym + i) = 0;
316 new_sym->
index = dlthis->
tramp.tramp_sym_next_index;
317 dlthis->
tramp.tramp_sym_next_index++;
329 dlthis->
tramp.symbol_head = new_sym;
331 dlthis->
tramp.symbol_tail->next = new_sym;
333 dlthis->
tramp.symbol_tail = new_sym;
351 for (sym_found = dlthis->
tramp.symbol_head;
352 sym_found !=
NULL; sym_found = sym_found->
next) {
353 if (sym_found->
str_index == string_index)
374 str_found = priv_tramp_string_find(dlthis,
string);
375 if (str_found !=
NULL)
376 sym_found = priv_tramp_sym_get(dlthis, str_found->
index);
388 static int priv_tramp_sym_finalize(
struct dload_state *dlthis)
398 dlthis->
tramp.final_sym_table =
401 tramp_sym_next_index));
402 if (dlthis->
tramp.final_sym_table !=
NULL) {
406 new_sym = dlthis->
tramp.final_sym_table;
407 cur_sym = dlthis->
tramp.symbol_head;
408 while (cur_sym !=
NULL) {
410 dlthis->
tramp.symbol_head = cur_sym->
next;
411 if (cur_sym == dlthis->
tramp.symbol_tail)
425 if (new_sym->
secnn < 0) {
431 dlthis->
mysym->dload_deallocate(dlthis->
mysym, cur_sym);
434 cur_sym = dlthis->
tramp.symbol_head;
440 dload_error(dlthis,
"Failed to alloc trampoline sym table");
457 u32 pkt_size = tramp_img_pkt_size_get();
467 if (new_img_pkt !=
NULL) {
472 pkt_data = (
u8 *) &new_img_pkt->
hdr;
473 gen_tbl_entry = (
u8 *) &tramp_gen_info[gen_index];
474 for (i = 0; i < pkt_size; i++) {
475 *pkt_data = *gen_tbl_entry;
483 new_img_pkt->
hdr.relo_offset);
484 for (i = 0; i < new_img_pkt->
hdr.num_relos; i++)
488 new_img_pkt->
next = dlthis->
tramp.tramp_pkts;
489 dlthis->
tramp.tramp_pkts = new_img_pkt;
516 for (i = 0; i < relo_count; i++)
531 static int priv_tramp_pkt_finalize(
struct dload_state *dlthis)
545 cur_pkt = dlthis->
tramp.tramp_pkts;
546 while ((ret_val != 0) && (cur_pkt !=
NULL)) {
548 dlthis->
tramp.tramp_pkts = cur_pkt->
next;
558 cur_pkt->
hdr.relo_offset);
559 while (relos_done < cur_pkt->
hdr.num_relos) {
560 #ifdef ENABLE_TRAMP_DEBUG
562 "===> Trampoline %x branches to %x",
566 tramp.final_sym_table[cur_relo->
572 ((i + relos_done) < cur_pkt->
hdr.num_relos)); i++)
573 relos[i] = cur_relo + i;
576 ret_val = priv_pkt_relo(dlthis,
581 "Relocation of trampoline pkt at %x"
582 " failed", cur_pkt->
base +
595 ret_val = dlthis->
myio->writemem(dlthis->
myio,
611 dlthis->
mysym->dload_deallocate(dlthis->
mysym, cur_pkt);
614 cur_pkt = dlthis->
tramp.tramp_pkts;
631 static int priv_dup_pkt_finalize(
struct dload_state *dlthis)
645 cur_pkt = dlthis->
tramp.dup_pkts;
646 while ((ret_val != 0) && (cur_pkt !=
NULL)) {
664 while (cur_relo !=
NULL) {
667 && (cur_relo !=
NULL);
668 i++, cur_relo = cur_relo->
next) {
669 relos[
i] = &cur_relo->relo;
674 ret_val = priv_pkt_relo(dlthis,
679 "Relocation of dup pkt at %x"
680 " failed", cur_pkt->
offset +
687 dlthis->
mysym->dload_deallocate(dlthis->
mysym,
702 ret_val = dlthis->
myio->writemem(dlthis->
myio,
719 dlthis->
mysym->dload_deallocate(dlthis->
mysym, cur_pkt);
722 cur_pkt = dlthis->
tramp.dup_pkts;
740 for (cur_pkt = dlthis->
tramp.dup_pkts;
741 cur_pkt !=
NULL; cur_pkt = cur_pkt->
next) {
742 if ((cur_pkt->
secnn == secnn) &&
743 (cur_pkt->
offset == image_offset)) {
764 static int priv_img_pkt_dup(
struct dload_state *dlthis,
765 s16 secnn,
u32 image_offset,
778 dup_pkt = priv_dup_find(dlthis, secnn, image_offset);
780 if (dup_pkt ==
NULL) {
784 ipacket->packet_size;
787 dlthis->
mysym->dload_allocate(dlthis->
mysym, new_dup_size);
788 if (dup_pkt !=
NULL) {
790 dup_pkt->secnn =
secnn;
791 dup_pkt->offset = image_offset;
792 dup_pkt->relo_chain =
NULL;
795 dup_pkt->img_pkt = *ipacket;
796 dup_pkt->img_pkt.
img_data = (
u8 *) (dup_pkt + 1);
798 *(dup_pkt->img_pkt.img_data + i) =
802 dup_pkt->next = dlthis->
tramp.dup_pkts;
803 dlthis->
tramp.dup_pkts = dup_pkt;
805 dload_error(dlthis,
"Failed to create dup packet!");
811 for (i = 0; i < dup_pkt->img_pkt.packet_size; i++)
812 *(dup_pkt->img_pkt.img_data + i) =
818 if (dup_pkt !=
NULL) {
823 dup_relo = dlthis->
mysym->dload_allocate(dlthis->
mysym,
825 if (dup_relo !=
NULL) {
829 dup_relo->
relo.SYMNDX = new_tramp_sym->
index;
831 dup_relo->
next = dup_pkt->relo_chain;
832 dup_pkt->relo_chain = dup_relo;
852 bool ret_val =
false;
858 gen_index = tramp_map[map_index];
891 gen_index = tramp_map[map_index];
896 priv_tramp_string_create(dlthis,
900 #ifdef ENABLE_TRAMP_DEBUG
902 "Trampoline at img loc %x, references %x",
904 image_offset + rp->
vaddr,
912 if (rp->SYMNDX == -1) {
916 ref_sym = &ext_tmp_sym;
920 priv_tramp_sym_gen_name(ref_sym->
value, tramp_sym_str);
921 new_tramp_sym = priv_tramp_sym_find(dlthis, tramp_sym_str);
922 if (new_tramp_sym ==
NULL) {
926 new_tramp_str = priv_tramp_string_create(dlthis,
930 if (new_tramp_str ==
NULL) {
932 "trampoline string\n");
937 new_tramp_base = priv_tramp_sect_alloc(dlthis,
942 tmp_sym.
value = new_tramp_base;
946 new_tramp_sym = priv_tramp_sym_create(dlthis,
951 new_ext_sym = priv_tramp_sym_create(dlthis, -1,
954 if ((new_tramp_sym !=
NULL) &&
955 (new_ext_sym !=
NULL)) {
960 ret_val = priv_tgt_img_gen(dlthis,
976 new_tramp_sym, new_ext_sym);
986 ret_val = priv_img_pkt_dup(dlthis, secnn, image_offset,
987 ipacket, rp, new_tramp_sym);
990 "original img pkt\n");
1017 dup_pkt = priv_dup_find(dlthis, secnn, image_offset);
1018 if (dup_pkt !=
NULL) {
1019 for (i = 0; i < dup_pkt->
img_pkt.packet_size; i++)
1020 *(dup_pkt->
img_pkt.img_data + i) =
1026 "Unable to find existing DUP pkt for %x, offset %x",
1027 secnn, image_offset);
1046 if (dlthis->
tramp.tramp_sect_next_addr != 0) {
1049 ret_val = priv_string_tbl_finalize(dlthis);
1054 ret_val = priv_tramp_sect_tgt_alloc(dlthis);
1059 ret_val = priv_tramp_sym_finalize(dlthis);
1065 ret_val = priv_tramp_pkt_finalize(dlthis);
1069 ret_val = priv_dup_pkt_finalize(dlthis);
1103 dlthis->
mysym->dload_deallocate(dlthis->
mysym, cur_sym);
1107 dlthis->
mysym->dload_deallocate(dlthis->
mysym,
1116 dlthis->
mysym->dload_deallocate(dlthis->
mysym, cur_string);
1120 dlthis->
mysym->dload_deallocate(dlthis->
mysym,
1126 dlthis->
mysym->dload_deallocate(dlthis->
mysym, cur_tramp_pkt);
1129 for (cur_dup_pkt = tramp->
dup_pkts;
1134 cur_dup_relo !=
NULL;
1137 dlthis->
mysym->dload_deallocate(dlthis->
mysym,
1141 dlthis->
mysym->dload_deallocate(dlthis->
mysym, cur_dup_pkt);