| /* |
| * dload_internal.h |
| * |
| * DSP-BIOS Bridge driver support functions for TI OMAP processors. |
| * |
| * Copyright (C) 2005-2006 Texas Instruments, Inc. |
| * |
| * This package is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| * |
| * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
| * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
| */ |
| |
| #ifndef _DLOAD_INTERNAL_ |
| #define _DLOAD_INTERNAL_ |
| |
| #include <linux/types.h> |
| |
| /* |
| * Internal state definitions for the dynamic loader |
| */ |
| |
| /* type used for relocation intermediate results */ |
| typedef s32 rvalue; |
| |
| /* unsigned version of same; must have at least as many bits */ |
| typedef u32 urvalue; |
| |
| /* |
| * Dynamic loader configuration constants |
| */ |
| /* error issued if input has more sections than this limit */ |
| #define REASONABLE_SECTION_LIMIT 100 |
| |
| /* (Addressable unit) value used to clear BSS section */ |
| #define DLOAD_FILL_BSS 0 |
| |
| /* |
| * Reorder maps explained (?) |
| * |
| * The doff file format defines a 32-bit pattern used to determine the |
| * byte order of an image being read. That value is |
| * BYTE_RESHUFFLE_VALUE == 0x00010203 |
| * For purposes of the reorder routine, we would rather have the all-is-OK |
| * for 32-bits pattern be 0x03020100. This first macro makes the |
| * translation from doff file header value to MAP value: */ |
| #define REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303) |
| /* This translation is made in dload_headers. Thereafter, the all-is-OK |
| * value for the maps stored in dlthis is REORDER_MAP(BYTE_RESHUFFLE_VALUE). |
| * But sadly, not all bits of the doff file are 32-bit integers. |
| * The notable exceptions are strings and image bits. |
| * Strings obey host byte order: */ |
| #if defined(_BIG_ENDIAN) |
| #define HOST_BYTE_ORDER(cookedmap) ((cookedmap) ^ 0x3030303) |
| #else |
| #define HOST_BYTE_ORDER(cookedmap) (cookedmap) |
| #endif |
| /* Target bits consist of target AUs (could be bytes, or 16-bits, |
| * or 32-bits) stored as an array in host order. A target order |
| * map is defined by: */ |
| #if !defined(_BIG_ENDIAN) || TARGET_AU_BITS > 16 |
| #define TARGET_ORDER(cookedmap) (cookedmap) |
| #elif TARGET_AU_BITS > 8 |
| #define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x2020202) |
| #else |
| #define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x3030303) |
| #endif |
| |
| /* forward declaration for handle returned by dynamic loader */ |
| struct my_handle; |
| |
| /* |
| * a list of module handles, which mirrors the debug list on the target |
| */ |
| struct dbg_mirror_root { |
| /* must be same as dbg_mirror_list; __DLModules address on target */ |
| u32 dbthis; |
| struct my_handle *next; /* must be same as dbg_mirror_list */ |
| u16 changes; /* change counter */ |
| u16 refcount; /* number of modules referencing this root */ |
| }; |
| |
| struct dbg_mirror_list { |
| u32 dbthis; |
| struct my_handle *next, *prev; |
| struct dbg_mirror_root *root; |
| u16 dbsiz; |
| u32 context; /* Save context for .dllview memory allocation */ |
| }; |
| |
| #define VARIABLE_SIZE 1 |
| /* |
| * the structure we actually return as an opaque module handle |
| */ |
| struct my_handle { |
| struct dbg_mirror_list dm; /* !!! must be first !!! */ |
| /* sections following << 1, LSB is set for big-endian target */ |
| u16 secn_count; |
| struct ldr_section_info secns[VARIABLE_SIZE]; |
| }; |
| #define MY_HANDLE_SIZE (sizeof(struct my_handle) -\ |
| sizeof(struct ldr_section_info)) |
| /* real size of my_handle */ |
| |
| /* |
| * reduced symbol structure used for symbols during relocation |
| */ |
| struct local_symbol { |
| s32 value; /* Relocated symbol value */ |
| s32 delta; /* Original value in input file */ |
| s16 secnn; /* section number */ |
| s16 sclass; /* symbol class */ |
| }; |
| |
| /* |
| * Trampoline data structures |
| */ |
| #define TRAMP_NO_GEN_AVAIL 65535 |
| #define TRAMP_SYM_PREFIX "__$dbTR__" |
| #define TRAMP_SECT_NAME ".dbTR" |
| /* MUST MATCH THE LENGTH ABOVE!! */ |
| #define TRAMP_SYM_PREFIX_LEN 9 |
| /* Includes NULL termination */ |
| #define TRAMP_SYM_HEX_ASCII_LEN 9 |
| |
| #define GET_CONTAINER(ptr, type, field) ((type *)((unsigned long)ptr -\ |
| (unsigned long)(&((type *)0)->field))) |
| #ifndef FIELD_OFFSET |
| #define FIELD_OFFSET(type, field) ((unsigned long)(&((type *)0)->field)) |
| #endif |
| |
| /* |
| The trampoline code for the target is located in a table called |
| "tramp_gen_info" with is indexed by looking up the index in the table |
| "tramp_map". The tramp_map index is acquired using the target |
| HASH_FUNC on the relocation type that caused the trampoline. Each |
| trampoline code table entry MUST follow this format: |
| |
| |----------------------------------------------| |
| | tramp_gen_code_hdr | |
| |----------------------------------------------| |
| | Trampoline image code | |
| | (the raw instruction code for the target) | |
| |----------------------------------------------| |
| | Relocation entries for the image code | |
| |----------------------------------------------| |
| |
| This is very similar to how image data is laid out in the DOFF file |
| itself. |
| */ |
| struct tramp_gen_code_hdr { |
| u32 tramp_code_size; /* in BYTES */ |
| u32 num_relos; |
| u32 relo_offset; /* in BYTES */ |
| }; |
| |
| struct tramp_img_pkt { |
| struct tramp_img_pkt *next; /* MUST BE FIRST */ |
| u32 base; |
| struct tramp_gen_code_hdr hdr; |
| u8 payload[VARIABLE_SIZE]; |
| }; |
| |
| struct tramp_img_dup_relo { |
| struct tramp_img_dup_relo *next; |
| struct reloc_record_t relo; |
| }; |
| |
| struct tramp_img_dup_pkt { |
| struct tramp_img_dup_pkt *next; /* MUST BE FIRST */ |
| s16 secnn; |
| u32 offset; |
| struct image_packet_t img_pkt; |
| struct tramp_img_dup_relo *relo_chain; |
| |
| /* PAYLOAD OF IMG PKT FOLLOWS */ |
| }; |
| |
| struct tramp_sym { |
| struct tramp_sym *next; /* MUST BE FIRST */ |
| u32 index; |
| u32 str_index; |
| struct local_symbol sym_info; |
| }; |
| |
| struct tramp_string { |
| struct tramp_string *next; /* MUST BE FIRST */ |
| u32 index; |
| char str[VARIABLE_SIZE]; /* NULL terminated */ |
| }; |
| |
| struct tramp_info { |
| u32 tramp_sect_next_addr; |
| struct ldr_section_info sect_info; |
| |
| struct tramp_sym *symbol_head; |
| struct tramp_sym *symbol_tail; |
| u32 tramp_sym_next_index; |
| struct local_symbol *final_sym_table; |
| |
| struct tramp_string *string_head; |
| struct tramp_string *string_tail; |
| u32 tramp_string_next_index; |
| u32 tramp_string_size; |
| char *final_string_table; |
| |
| struct tramp_img_pkt *tramp_pkts; |
| struct tramp_img_dup_pkt *dup_pkts; |
| }; |
| |
| /* |
| * States of the .cinit state machine |
| */ |
| enum cinit_mode { |
| CI_COUNT = 0, /* expecting a count */ |
| CI_ADDRESS, /* expecting an address */ |
| #if CINIT_ALIGN < CINIT_ADDRESS /* handle case of partial address field */ |
| CI_PARTADDRESS, /* have only part of the address */ |
| #endif |
| CI_COPY, /* in the middle of copying data */ |
| CI_DONE /* end of .cinit table */ |
| }; |
| |
| /* |
| * The internal state of the dynamic loader, which is passed around as |
| * an object |
| */ |
| struct dload_state { |
| struct dynamic_loader_stream *strm; /* The module input stream */ |
| struct dynamic_loader_sym *mysym; /* Symbols for this session */ |
| /* target memory allocator */ |
| struct dynamic_loader_allocate *myalloc; |
| struct dynamic_loader_initialize *myio; /* target memory initializer */ |
| unsigned myoptions; /* Options parameter dynamic_load_module */ |
| |
| char *str_head; /* Pointer to string table */ |
| #if BITS_PER_AU > BITS_PER_BYTE |
| char *str_temp; /* Pointer to temporary buffer for strings */ |
| /* big enough to hold longest string */ |
| unsigned temp_len; /* length of last temporary string */ |
| char *xstrings; /* Pointer to buffer for expanded */ |
| /* strings for sec names */ |
| #endif |
| /* Total size of strings for DLLView section names */ |
| unsigned debug_string_size; |
| /* Pointer to parallel section info for allocated sections only */ |
| struct doff_scnhdr_t *sect_hdrs; /* Pointer to section table */ |
| struct ldr_section_info *ldr_sections; |
| #if TMS32060 |
| /* The address of the start of the .bss section */ |
| ldr_addr bss_run_base; |
| #endif |
| struct local_symbol *local_symtab; /* Relocation symbol table */ |
| |
| /* pointer to DL section info for the section being relocated */ |
| struct ldr_section_info *image_secn; |
| /* change in run address for current section during relocation */ |
| ldr_addr delta_runaddr; |
| ldr_addr image_offset; /* offset of current packet in section */ |
| enum cinit_mode cinit_state; /* current state of cload_cinit() */ |
| int cinit_count; /* the current count */ |
| ldr_addr cinit_addr; /* the current address */ |
| s16 cinit_page; /* the current page */ |
| /* Handle to be returned by dynamic_load_module */ |
| struct my_handle *myhandle; |
| unsigned dload_errcount; /* Total # of errors reported so far */ |
| /* Number of target sections that require allocation and relocation */ |
| unsigned allocated_secn_count; |
| #ifndef TARGET_ENDIANNESS |
| int big_e_target; /* Target data in big-endian format */ |
| #endif |
| /* map for reordering bytes, 0 if not needed */ |
| u32 reorder_map; |
| struct doff_filehdr_t dfile_hdr; /* DOFF file header structure */ |
| struct doff_verify_rec_t verify; /* Verify record */ |
| |
| struct tramp_info tramp; /* Trampoline data, if needed */ |
| |
| int relstkidx; /* index into relocation value stack */ |
| /* relocation value stack used in relexp.c */ |
| rvalue relstk[STATIC_EXPR_STK_SIZE]; |
| |
| }; |
| |
| #ifdef TARGET_ENDIANNESS |
| #define TARGET_BIG_ENDIAN TARGET_ENDIANNESS |
| #else |
| #define TARGET_BIG_ENDIAN (dlthis->big_e_target) |
| #endif |
| |
| /* |
| * Exports from cload.c to rest of the world |
| */ |
| extern void dload_error(struct dload_state *dlthis, const char *errtxt, ...); |
| extern void dload_syms_error(struct dynamic_loader_sym *syms, |
| const char *errtxt, ...); |
| extern void dload_headers(struct dload_state *dlthis); |
| extern void dload_strings(struct dload_state *dlthis, bool sec_names_only); |
| extern void dload_sections(struct dload_state *dlthis); |
| extern void dload_reorder(void *data, int dsiz, u32 map); |
| extern u32 dload_checksum(void *data, unsigned siz); |
| |
| #if HOST_ENDIANNESS |
| extern uint32_t dload_reverse_checksum(void *data, unsigned siz); |
| #if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32) |
| extern uint32_t dload_reverse_checksum16(void *data, unsigned siz); |
| #endif |
| #endif |
| |
| /* |
| * exported by reloc.c |
| */ |
| extern void dload_relocate(struct dload_state *dlthis, tgt_au_t *data, |
| struct reloc_record_t *rp, bool *tramps_generated, |
| bool second_pass); |
| |
| extern rvalue dload_unpack(struct dload_state *dlthis, tgt_au_t *data, |
| int fieldsz, int offset, unsigned sgn); |
| |
| extern int dload_repack(struct dload_state *dlthis, rvalue val, tgt_au_t *data, |
| int fieldsz, int offset, unsigned sgn); |
| |
| /* |
| * exported by tramp.c |
| */ |
| extern bool dload_tramp_avail(struct dload_state *dlthis, |
| struct reloc_record_t *rp); |
| |
| int dload_tramp_generate(struct dload_state *dlthis, s16 secnn, |
| u32 image_offset, struct image_packet_t *ipacket, |
| struct reloc_record_t *rp); |
| |
| extern int dload_tramp_pkt_udpate(struct dload_state *dlthis, |
| s16 secnn, u32 image_offset, |
| struct image_packet_t *ipacket); |
| |
| extern int dload_tramp_finalize(struct dload_state *dlthis); |
| |
| extern void dload_tramp_cleanup(struct dload_state *dlthis); |
| |
| #endif /* _DLOAD_INTERNAL_ */ |