📄 hw_htab.c
字号:
status = device_instance_call_method(memory, "claim", 3, args, 1, results); if (status != 0) device_error(me, "failed to claim memory"); return results[0];}static voidhtab_map_region(device *me, device_instance *memory, unsigned_word pte_ra, unsigned64 pte_va, unsigned nr_bytes, unsigned wimg, unsigned pp, unsigned32 htaborg, unsigned32 htabmask){ unsigned_word ra; unsigned64 va; /* claim the memory */ if (memory != NULL) claim_memory(me, memory, pte_ra, nr_bytes); /* go through all pages and create a pte for each */ for (ra = pte_ra, va = pte_va; ra < pte_ra + nr_bytes; ra += 0x1000, va += 0x1000) { htab_map_page(me, ra, va, wimg, pp, htaborg, htabmask); }} typedef struct _htab_binary_sizes { unsigned_word text_ra; unsigned_word text_base; unsigned_word text_bound; unsigned_word data_ra; unsigned_word data_base; unsigned data_bound; device *me;} htab_binary_sizes;static voidhtab_sum_binary(bfd *abfd, sec_ptr sec, PTR data){ htab_binary_sizes *sizes = (htab_binary_sizes*)data; unsigned_word size = bfd_get_section_size (sec); unsigned_word vma = bfd_get_section_vma (abfd, sec);#define bfd_get_section_lma(abfd, sec) ((sec)->lma + 0) unsigned_word ra = bfd_get_section_lma (abfd, sec); /* skip the section if no memory to allocate */ if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC)) return; if ((bfd_get_section_flags (abfd, sec) & SEC_CODE) || (bfd_get_section_flags (abfd, sec) & SEC_READONLY)) { if (sizes->text_bound < vma + size) sizes->text_bound = ALIGN_PAGE(vma + size); if (sizes->text_base > vma) sizes->text_base = FLOOR_PAGE(vma); if (sizes->text_ra > ra) sizes->text_ra = FLOOR_PAGE(ra); } else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA) || (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)) { if (sizes->data_bound < vma + size) sizes->data_bound = ALIGN_PAGE(vma + size); if (sizes->data_base > vma) sizes->data_base = FLOOR_PAGE(vma); if (sizes->data_ra > ra) sizes->data_ra = FLOOR_PAGE(ra); }}static voidhtab_dma_binary(bfd *abfd, sec_ptr sec, PTR data){ htab_binary_sizes *sizes = (htab_binary_sizes*)data; void *section_init; unsigned_word section_vma; unsigned_word section_size; unsigned_word section_ra; device *me = sizes->me; /* skip the section if no memory to allocate */ if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC)) return; /* check/ignore any sections of size zero */ section_size = bfd_get_section_size (sec); if (section_size == 0) return; /* if nothing to load, ignore this one */ if (! (bfd_get_section_flags(abfd, sec) & SEC_LOAD)) return; /* find where it is to go */ section_vma = bfd_get_section_vma(abfd, sec); section_ra = 0; if ((bfd_get_section_flags (abfd, sec) & SEC_CODE) || (bfd_get_section_flags (abfd, sec) & SEC_READONLY)) section_ra = (section_vma - sizes->text_base + sizes->text_ra); else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)) section_ra = (section_vma - sizes->data_base + sizes->data_ra); else return; /* just ignore it */ DTRACE(htab, ("load - name=%-7s vma=0x%.8lx size=%6ld ra=0x%.8lx flags=%3lx(%s%s%s%s%s )\n", bfd_get_section_name(abfd, sec), (long)section_vma, (long)section_size, (long)section_ra, (long)bfd_get_section_flags(abfd, sec), bfd_get_section_flags(abfd, sec) & SEC_LOAD ? " LOAD" : "", bfd_get_section_flags(abfd, sec) & SEC_CODE ? " CODE" : "", bfd_get_section_flags(abfd, sec) & SEC_DATA ? " DATA" : "", bfd_get_section_flags(abfd, sec) & SEC_ALLOC ? " ALLOC" : "", bfd_get_section_flags(abfd, sec) & SEC_READONLY ? " READONLY" : "" )); /* dma in the sections data */ section_init = zalloc(section_size); if (!bfd_get_section_contents(abfd, sec, section_init, 0, section_size)) { bfd_perror("devices/pte"); device_error(me, "no data loaded"); } if (device_dma_write_buffer(device_parent(me), section_init, 0 /*space*/, section_ra, section_size, 1 /*violate_read_only*/) != section_size) device_error(me, "broken dma transfer"); zfree(section_init); /* only free if load */}/* create a memory map from a binaries virtual addresses to a copy of the binary laid out linearly in memory */static voidhtab_map_binary(device *me, device_instance *memory, unsigned_word ra, unsigned wimg, unsigned pp, const char *file_name, unsigned32 htaborg, unsigned32 htabmask){ htab_binary_sizes sizes; bfd *image; sizes.text_ra = -1; sizes.data_ra = -1; sizes.text_base = -1; sizes.data_base = -1; sizes.text_bound = 0; sizes.data_bound = 0; sizes.me = me; /* open the file */ image = bfd_openr(file_name, NULL); if (image == NULL) { bfd_perror("devices/pte"); device_error(me, "the file %s not loaded", file_name); } /* check it is valid */ if (!bfd_check_format(image, bfd_object)) { bfd_close(image); device_error(me, "the file %s has an invalid binary format", file_name); } /* determine the size of each of the files regions */ bfd_map_over_sections (image, htab_sum_binary, (PTR) &sizes); /* if needed, determine the real addresses of the sections */ if (ra != -1) { sizes.text_ra = ra; sizes.data_ra = ALIGN_PAGE(sizes.text_ra + (sizes.text_bound - sizes.text_base)); } DTRACE(htab, ("text map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n", (unsigned long)sizes.text_base, (unsigned long)sizes.text_bound, (unsigned long)sizes.text_ra)); DTRACE(htab, ("data map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n", (unsigned long)sizes.data_base, (unsigned long)sizes.data_bound, (unsigned long)sizes.data_ra)); /* check for and fix a botched image (text and data segments overlap) */ if ((sizes.text_base <= sizes.data_base && sizes.text_bound >= sizes.data_bound) || (sizes.data_base <= sizes.text_base && sizes.data_bound >= sizes.data_bound) || (sizes.text_bound > sizes.data_base && sizes.text_bound <= sizes.data_bound) || (sizes.text_base >= sizes.data_base && sizes.text_base < sizes.data_bound)) { DTRACE(htab, ("text and data segment overlaped - using just data segment\n")); /* check va->ra linear */ if ((sizes.text_base - sizes.text_ra) != (sizes.data_base - sizes.data_ra)) device_error(me, "overlapping but missaligned text and data segments"); /* enlarge the data segment */ if (sizes.text_base < sizes.data_base) sizes.data_base = sizes.text_base; if (sizes.text_bound > sizes.data_bound) sizes.data_bound = sizes.text_bound; if (sizes.text_ra < sizes.data_ra) sizes.data_ra = sizes.text_ra; /* zap the text segment */ sizes.text_base = 0; sizes.text_bound = 0; sizes.text_ra = 0; DTRACE(htab, ("common map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n", (unsigned long)sizes.data_base, (unsigned long)sizes.data_bound, (unsigned long)sizes.data_ra)); } /* set up virtual memory maps for each of the regions */ if (sizes.text_bound - sizes.text_base > 0) { htab_map_region(me, memory, sizes.text_ra, sizes.text_base, sizes.text_bound - sizes.text_base, wimg, pp, htaborg, htabmask); } htab_map_region(me, memory, sizes.data_ra, sizes.data_base, sizes.data_bound - sizes.data_base, wimg, pp, htaborg, htabmask); /* dma the sections into physical memory */ bfd_map_over_sections (image, htab_dma_binary, (PTR) &sizes);}static voidhtab_init_data_callback(device *me){ device_instance *memory = NULL; if (WITH_TARGET_WORD_BITSIZE != 32) device_error(me, "only 32bit targets currently suported"); /* find memory device */ if (device_find_property(me, "claim") != NULL) memory = tree_find_ihandle_property(me, "/chosen/memory"); /* for the htab, just allocate space for it */ if (strcmp(device_name(me), "htab") == 0) { unsigned_word address = device_find_integer_property(me, "real-address"); unsigned_word length = device_find_integer_property(me, "nr-bytes"); unsigned_word base = claim_memory(me, memory, address, length); if (base == -1 || base != address) device_error(me, "cannot allocate hash table"); } /* for the pte, do all the real work */ if (strcmp(device_name(me), "pte") == 0) { unsigned32 htaborg; unsigned32 htabmask; htab_decode_hash_table(me, &htaborg, &htabmask); if (device_find_property(me, "file-name") != NULL) { /* map in a binary */ unsigned pte_wimg = device_find_integer_property(me, "wimg"); unsigned pte_pp = device_find_integer_property(me, "pp"); const char *file_name = device_find_string_property(me, "file-name"); if (device_find_property(me, "real-address") != NULL) { unsigned32 pte_ra = device_find_integer_property(me, "real-address"); DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, file-name=%s\n", (unsigned long)pte_ra, (unsigned long)pte_wimg, (long)pte_pp, file_name)); htab_map_binary(me, memory, pte_ra, pte_wimg, pte_pp, file_name, htaborg, htabmask); } else { DTRACE(htab, ("pte - wimg=%ld, pp=%ld, file-name=%s\n", (unsigned long)pte_wimg, (long)pte_pp, file_name)); htab_map_binary(me, memory, -1, pte_wimg, pte_pp, file_name, htaborg, htabmask); } } else { /* handle a normal mapping definition */ unsigned64 pte_va = 0; unsigned32 pte_ra = device_find_integer_property(me, "real-address"); unsigned pte_nr_bytes = device_find_integer_property(me, "nr-bytes"); unsigned pte_wimg = device_find_integer_property(me, "wimg"); unsigned pte_pp = device_find_integer_property(me, "pp"); signed_cell partial_va; int i; for (i = 0; device_find_integer_array_property(me, "virtual-address", i, &partial_va); i++) { pte_va = (pte_va << WITH_TARGET_WORD_BITSIZE) | (unsigned_cell)partial_va; } DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, va=0x%lx, nr_bytes=%ld\n", (unsigned long)pte_ra, (long)pte_wimg, (long)pte_pp, (unsigned long)pte_va, (long)pte_nr_bytes)); htab_map_region(me, memory, pte_ra, pte_va, pte_nr_bytes, pte_wimg, pte_pp, htaborg, htabmask); } }}static device_callbacks const htab_callbacks = { { NULL, htab_init_data_callback, }, { NULL, }, /* address */ { NULL, }, /* IO */ { passthrough_device_dma_read_buffer, passthrough_device_dma_write_buffer, }, { NULL, }, /* interrupt */ { generic_device_unit_decode, generic_device_unit_encode, },};const device_descriptor hw_htab_device_descriptor[] = { { "htab", NULL, &htab_callbacks }, { "pte", NULL, &htab_callbacks }, /* yep - uses htab's table */ { NULL },};#endif /* _HW_HTAB_C_ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -