1/* 2 * dbll.c 3 * 4 * DSP-BIOS Bridge driver support functions for TI OMAP processors. 5 * 6 * Copyright (C) 2005-2006 Texas Instruments, Inc. 7 * 8 * This package is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 13 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 14 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 15 */ 16#include <linux/types.h> 17 18/* ----------------------------------- Host OS */ 19#include <dspbridge/host_os.h> 20 21/* ----------------------------------- DSP/BIOS Bridge */ 22#include <dspbridge/dbdefs.h> 23 24/* ----------------------------------- Trace & Debug */ 25#include <dspbridge/dbc.h> 26#include <dspbridge/gh.h> 27 28/* ----------------------------------- OS Adaptation Layer */ 29 30/* Dynamic loader library interface */ 31#include <dspbridge/dynamic_loader.h> 32#include <dspbridge/getsection.h> 33 34/* ----------------------------------- This */ 35#include <dspbridge/dbll.h> 36#include <dspbridge/rmm.h> 37 38/* Number of buckets for symbol hash table */ 39#define MAXBUCKETS 211 40 41/* Max buffer length */ 42#define MAXEXPR 128 43 44#define DOFF_ALIGN(x) (((x) + 3) & ~3UL) 45 46/* 47 * ======== struct dbll_tar_obj* ======== 48 * A target may have one or more libraries of symbols/code/data loaded 49 * onto it, where a library is simply the symbols/code/data contained 50 * in a DOFF file. 51 */ 52/* 53 * ======== dbll_tar_obj ======== 54 */ 55struct dbll_tar_obj { 56 struct dbll_attrs attrs; 57 struct dbll_library_obj *head; /* List of all opened libraries */ 58}; 59 60/* 61 * The following 4 typedefs are "super classes" of the dynamic loader 62 * library types used in dynamic loader functions (dynamic_loader.h). 63 */ 64/* 65 * ======== dbll_stream ======== 66 * Contains dynamic_loader_stream 67 */ 68struct dbll_stream { 69 struct dynamic_loader_stream dl_stream; 70 struct dbll_library_obj *lib; 71}; 72 73/* 74 * ======== ldr_symbol ======== 75 */ 76struct ldr_symbol { 77 struct dynamic_loader_sym dl_symbol; 78 struct dbll_library_obj *lib; 79}; 80 81/* 82 * ======== dbll_alloc ======== 83 */ 84struct dbll_alloc { 85 struct dynamic_loader_allocate dl_alloc; 86 struct dbll_library_obj *lib; 87}; 88 89/* 90 * ======== dbll_init_obj ======== 91 */ 92struct dbll_init_obj { 93 struct dynamic_loader_initialize dl_init; 94 struct dbll_library_obj *lib; 95}; 96 97/* 98 * ======== DBLL_Library ======== 99 * A library handle is returned by DBLL_Open() and is passed to dbll_load() 100 * to load symbols/code/data, and to dbll_unload(), to remove the 101 * symbols/code/data loaded by dbll_load(). 102 */ 103 104/* 105 * ======== dbll_library_obj ======== 106 */ 107struct dbll_library_obj { 108 struct dbll_library_obj *next; /* Next library in target's list */ 109 struct dbll_library_obj *prev; /* Previous in the list */ 110 struct dbll_tar_obj *target_obj; /* target for this library */ 111 112 /* Objects needed by dynamic loader */ 113 struct dbll_stream stream; 114 struct ldr_symbol symbol; 115 struct dbll_alloc allocate; 116 struct dbll_init_obj init; 117 void *dload_mod_obj; 118 119 char *file_name; /* COFF file name */ 120 void *fp; /* Opaque file handle */ 121 u32 entry; /* Entry point */ 122 void *desc; /* desc of DOFF file loaded */ 123 u32 open_ref; /* Number of times opened */ 124 u32 load_ref; /* Number of times loaded */ 125 struct gh_t_hash_tab *sym_tab; /* Hash table of symbols */ 126 u32 ul_pos; 127}; 128 129/* 130 * ======== dbll_symbol ======== 131 */ 132struct dbll_symbol { 133 struct dbll_sym_val value; 134 char *name; 135}; 136 137static void dof_close(struct dbll_library_obj *zl_lib); 138static int dof_open(struct dbll_library_obj *zl_lib); 139static s32 no_op(struct dynamic_loader_initialize *thisptr, void *bufr, 140 ldr_addr locn, struct ldr_section_info *info, 141 unsigned bytsize); 142 143/* 144 * Functions called by dynamic loader 145 * 146 */ 147/* dynamic_loader_stream */ 148static int dbll_read_buffer(struct dynamic_loader_stream *this, void *buffer, 149 unsigned bufsize); 150static int dbll_set_file_posn(struct dynamic_loader_stream *this, 151 unsigned int pos); 152/* dynamic_loader_sym */ 153static struct dynload_symbol *dbll_find_symbol(struct dynamic_loader_sym *this, 154 const char *name); 155static struct dynload_symbol *dbll_add_to_symbol_table(struct dynamic_loader_sym 156 *this, const char *name, 157 unsigned module_id); 158static struct dynload_symbol *find_in_symbol_table(struct dynamic_loader_sym 159 *this, const char *name, 160 unsigned moduleid); 161static void dbll_purge_symbol_table(struct dynamic_loader_sym *this, 162 unsigned module_id); 163static void *allocate(struct dynamic_loader_sym *this, unsigned memsize); 164static void deallocate(struct dynamic_loader_sym *this, void *mem_ptr); 165static void dbll_err_report(struct dynamic_loader_sym *this, const char *errstr, 166 va_list args); 167/* dynamic_loader_allocate */ 168static int dbll_rmm_alloc(struct dynamic_loader_allocate *this, 169 struct ldr_section_info *info, unsigned align); 170static void rmm_dealloc(struct dynamic_loader_allocate *this, 171 struct ldr_section_info *info); 172 173/* dynamic_loader_initialize */ 174static int connect(struct dynamic_loader_initialize *this); 175static int read_mem(struct dynamic_loader_initialize *this, void *buf, 176 ldr_addr addr, struct ldr_section_info *info, 177 unsigned bytes); 178static int write_mem(struct dynamic_loader_initialize *this, void *buf, 179 ldr_addr addr, struct ldr_section_info *info, 180 unsigned nbytes); 181static int fill_mem(struct dynamic_loader_initialize *this, ldr_addr addr, 182 struct ldr_section_info *info, unsigned bytes, 183 unsigned val); 184static int execute(struct dynamic_loader_initialize *this, ldr_addr start); 185static void release(struct dynamic_loader_initialize *this); 186 187/* symbol table hash functions */ 188static u16 name_hash(void *key, u16 max_bucket); 189static bool name_match(void *key, void *sp); 190static void sym_delete(void *value); 191 192static u32 refs; /* module reference count */ 193 194/* Symbol Redefinition */ 195static int redefined_symbol; 196static int gbl_search = 1; 197 198/* 199 * ======== dbll_close ======== 200 */ 201void dbll_close(struct dbll_library_obj *zl_lib) 202{ 203 struct dbll_tar_obj *zl_target; 204 205 DBC_REQUIRE(refs > 0); 206 DBC_REQUIRE(zl_lib); 207 DBC_REQUIRE(zl_lib->open_ref > 0); 208 zl_target = zl_lib->target_obj; 209 zl_lib->open_ref--; 210 if (zl_lib->open_ref == 0) { 211 /* Remove library from list */ 212 if (zl_target->head == zl_lib) 213 zl_target->head = zl_lib->next; 214 215 if (zl_lib->prev) 216 (zl_lib->prev)->next = zl_lib->next; 217 218 if (zl_lib->next) 219 (zl_lib->next)->prev = zl_lib->prev; 220 221 /* Free DOF resources */ 222 dof_close(zl_lib); 223 kfree(zl_lib->file_name); 224 225 /* remove symbols from symbol table */ 226 if (zl_lib->sym_tab) 227 gh_delete(zl_lib->sym_tab); 228 229 /* remove the library object itself */ 230 kfree(zl_lib); 231 zl_lib = NULL; 232 } 233} 234 235/* 236 * ======== dbll_create ======== 237 */ 238int dbll_create(struct dbll_tar_obj **target_obj, 239 struct dbll_attrs *pattrs) 240{ 241 struct dbll_tar_obj *pzl_target; 242 int status = 0; 243 244 DBC_REQUIRE(refs > 0); 245 DBC_REQUIRE(pattrs != NULL); 246 DBC_REQUIRE(target_obj != NULL); 247 248 /* Allocate DBL target object */ 249 pzl_target = kzalloc(sizeof(struct dbll_tar_obj), GFP_KERNEL); 250 if (target_obj != NULL) { 251 if (pzl_target == NULL) { 252 *target_obj = NULL; 253 status = -ENOMEM; 254 } else { 255 pzl_target->attrs = *pattrs; 256 *target_obj = (struct dbll_tar_obj *)pzl_target; 257 } 258 DBC_ENSURE((!status && *target_obj) || 259 (status && *target_obj == NULL)); 260 } 261 262 return status; 263} 264 265/* 266 * ======== dbll_delete ======== 267 */ 268void dbll_delete(struct dbll_tar_obj *target) 269{ 270 struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target; 271 272 DBC_REQUIRE(refs > 0); 273 DBC_REQUIRE(zl_target); 274 275 if (zl_target != NULL) 276 kfree(zl_target); 277 278} 279 280/* 281 * ======== dbll_exit ======== 282 * Discontinue usage of DBL module. 283 */ 284void dbll_exit(void) 285{ 286 DBC_REQUIRE(refs > 0); 287 288 refs--; 289 290 if (refs == 0) 291 gh_exit(); 292 293 DBC_ENSURE(refs >= 0); 294} 295 296/* 297 * ======== dbll_get_addr ======== 298 * Get address of name in the specified library. 299 */ 300bool dbll_get_addr(struct dbll_library_obj *zl_lib, char *name, 301 struct dbll_sym_val **sym_val) 302{ 303 struct dbll_symbol *sym; 304 bool status = false; 305 306 DBC_REQUIRE(refs > 0); 307 DBC_REQUIRE(zl_lib); 308 DBC_REQUIRE(name != NULL); 309 DBC_REQUIRE(sym_val != NULL); 310 DBC_REQUIRE(zl_lib->sym_tab != NULL); 311 312 sym = (struct dbll_symbol *)gh_find(zl_lib->sym_tab, name); 313 if (sym != NULL) { 314 *sym_val = &sym->value; 315 status = true; 316 } 317 318 dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p, status 0x%x\n", 319 __func__, zl_lib, name, sym_val, status); 320 return status; 321} 322 323/* 324 * ======== dbll_get_attrs ======== 325 * Retrieve the attributes of the target. 326 */ 327void dbll_get_attrs(struct dbll_tar_obj *target, struct dbll_attrs *pattrs) 328{ 329 struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target; 330 331 DBC_REQUIRE(refs > 0); 332 DBC_REQUIRE(zl_target); 333 DBC_REQUIRE(pattrs != NULL); 334 335 if ((pattrs != NULL) && (zl_target != NULL)) 336 *pattrs = zl_target->attrs; 337 338} 339 340/* 341 * ======== dbll_get_c_addr ======== 342 * Get address of a "C" name in the specified library. 343 */ 344bool dbll_get_c_addr(struct dbll_library_obj *zl_lib, char *name, 345 struct dbll_sym_val **sym_val) 346{ 347 struct dbll_symbol *sym; 348 char cname[MAXEXPR + 1]; 349 bool status = false; 350 351 DBC_REQUIRE(refs > 0); 352 DBC_REQUIRE(zl_lib); 353 DBC_REQUIRE(sym_val != NULL); 354 DBC_REQUIRE(zl_lib->sym_tab != NULL); 355 DBC_REQUIRE(name != NULL); 356 357 cname[0] = '_'; 358 359 strncpy(cname + 1, name, sizeof(cname) - 2); 360 cname[MAXEXPR] = '\0'; /* insure '\0' string termination */ 361 362 /* Check for C name, if not found */ 363 sym = (struct dbll_symbol *)gh_find(zl_lib->sym_tab, cname); 364 365 if (sym != NULL) { 366 *sym_val = &sym->value; 367 status = true; 368 } 369 370 return status; 371} 372 373/* 374 * ======== dbll_get_sect ======== 375 * Get the base address and size (in bytes) of a COFF section. 376 */ 377int dbll_get_sect(struct dbll_library_obj *lib, char *name, u32 *paddr, 378 u32 *psize) 379{ 380 u32 byte_size; 381 bool opened_doff = false; 382 const struct ldr_section_info *sect = NULL; 383 struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib; 384 int status = 0; 385 386 DBC_REQUIRE(refs > 0); 387 DBC_REQUIRE(name != NULL); 388 DBC_REQUIRE(paddr != NULL); 389 DBC_REQUIRE(psize != NULL); 390 DBC_REQUIRE(zl_lib); 391 392 /* If DOFF file is not open, we open it. */ 393 if (zl_lib != NULL) { 394 if (zl_lib->fp == NULL) { 395 status = dof_open(zl_lib); 396 if (!status) 397 opened_doff = true; 398 399 } else { 400 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, 401 zl_lib->ul_pos, 402 SEEK_SET); 403 } 404 } else { 405 status = -EFAULT; 406 } 407 if (!status) { 408 byte_size = 1; 409 if (dload_get_section_info(zl_lib->desc, name, §)) { 410 *paddr = sect->load_addr; 411 *psize = sect->size * byte_size; 412 /* Make sure size is even for good swap */ 413 if (*psize % 2) 414 (*psize)++; 415 416 /* Align size */ 417 *psize = DOFF_ALIGN(*psize); 418 } else { 419 status = -ENXIO; 420 } 421 } 422 if (opened_doff) { 423 dof_close(zl_lib); 424 opened_doff = false; 425 } 426 427 dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p psize: %p, " 428 "status 0x%x\n", __func__, lib, name, paddr, psize, status); 429 430 return status; 431} 432 433/* 434 * ======== dbll_init ======== 435 */ 436bool dbll_init(void) 437{ 438 DBC_REQUIRE(refs >= 0); 439 440 if (refs == 0) 441 gh_init(); 442 443 refs++; 444 445 return true; 446} 447 448/* 449 * ======== dbll_load ======== 450 */ 451int dbll_load(struct dbll_library_obj *lib, dbll_flags flags, 452 struct dbll_attrs *attrs, u32 *entry) 453{ 454 struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib; 455 struct dbll_tar_obj *dbzl; 456 bool got_symbols = true; 457 s32 err; 458 int status = 0; 459 bool opened_doff = false; 460 DBC_REQUIRE(refs > 0); 461 DBC_REQUIRE(zl_lib); 462 DBC_REQUIRE(entry != NULL); 463 DBC_REQUIRE(attrs != NULL); 464 465 /* 466 * Load if not already loaded. 467 */ 468 if (zl_lib->load_ref == 0 || !(flags & DBLL_DYNAMIC)) { 469 dbzl = zl_lib->target_obj; 470 dbzl->attrs = *attrs; 471 /* Create a hash table for symbols if not already created */ 472 if (zl_lib->sym_tab == NULL) { 473 got_symbols = false; 474 zl_lib->sym_tab = gh_create(MAXBUCKETS, 475 sizeof(struct dbll_symbol), 476 name_hash, 477 name_match, sym_delete); 478 if (zl_lib->sym_tab == NULL) 479 status = -ENOMEM; 480 481 } 482 /* 483 * Set up objects needed by the dynamic loader 484 */ 485 /* Stream */ 486 zl_lib->stream.dl_stream.read_buffer = dbll_read_buffer; 487 zl_lib->stream.dl_stream.set_file_posn = dbll_set_file_posn; 488 zl_lib->stream.lib = zl_lib; 489 /* Symbol */ 490 zl_lib->symbol.dl_symbol.find_matching_symbol = 491 dbll_find_symbol; 492 if (got_symbols) { 493 zl_lib->symbol.dl_symbol.add_to_symbol_table = 494 find_in_symbol_table; 495 } else { 496 zl_lib->symbol.dl_symbol.add_to_symbol_table = 497 dbll_add_to_symbol_table; 498 } 499 zl_lib->symbol.dl_symbol.purge_symbol_table = 500 dbll_purge_symbol_table; 501 zl_lib->symbol.dl_symbol.dload_allocate = allocate; 502 zl_lib->symbol.dl_symbol.dload_deallocate = deallocate; 503 zl_lib->symbol.dl_symbol.error_report = dbll_err_report; 504 zl_lib->symbol.lib = zl_lib; 505 /* Allocate */ 506 zl_lib->allocate.dl_alloc.dload_allocate = dbll_rmm_alloc; 507 zl_lib->allocate.dl_alloc.dload_deallocate = rmm_dealloc; 508 zl_lib->allocate.lib = zl_lib; 509 /* Init */ 510 zl_lib->init.dl_init.connect = connect; 511 zl_lib->init.dl_init.readmem = read_mem; 512 zl_lib->init.dl_init.writemem = write_mem; 513 zl_lib->init.dl_init.fillmem = fill_mem; 514 zl_lib->init.dl_init.execute = execute; 515 zl_lib->init.dl_init.release = release; 516 zl_lib->init.lib = zl_lib; 517 /* If COFF file is not open, we open it. */ 518 if (zl_lib->fp == NULL) { 519 status = dof_open(zl_lib); 520 if (!status) 521 opened_doff = true; 522 523 } 524 if (!status) { 525 zl_lib->ul_pos = (*(zl_lib->target_obj->attrs.ftell)) 526 (zl_lib->fp); 527 /* Reset file cursor */ 528 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, 529 (long)0, 530 SEEK_SET); 531 symbols_reloaded = true; 532 /* The 5th argument, DLOAD_INITBSS, tells the DLL 533 * module to zero-init all BSS sections. In general, 534 * this is not necessary and also increases load time. 535 * We may want to make this configurable by the user */ 536 err = dynamic_load_module(&zl_lib->stream.dl_stream, 537 &zl_lib->symbol.dl_symbol, 538 &zl_lib->allocate.dl_alloc, 539 &zl_lib->init.dl_init, 540 DLOAD_INITBSS, 541 &zl_lib->dload_mod_obj); 542 543 if (err != 0) { 544 status = -EILSEQ; 545 } else if (redefined_symbol) { 546 zl_lib->load_ref++; 547 dbll_unload(zl_lib, (struct dbll_attrs *)attrs); 548 redefined_symbol = false; 549 status = -EILSEQ; 550 } else { 551 *entry = zl_lib->entry; 552 } 553 } 554 } 555 if (!status) 556 zl_lib->load_ref++; 557 558 /* Clean up DOFF resources */ 559 if (opened_doff) 560 dof_close(zl_lib); 561 562 DBC_ENSURE(status || zl_lib->load_ref > 0); 563 564 dev_dbg(bridge, "%s: lib: %p flags: 0x%x entry: %p, status 0x%x\n", 565 __func__, lib, flags, entry, status); 566 567 return status; 568} 569 570/* 571 * ======== dbll_load_sect ======== 572 * Not supported for COFF. 573 */ 574int dbll_load_sect(struct dbll_library_obj *zl_lib, char *sec_name, 575 struct dbll_attrs *attrs) 576{ 577 DBC_REQUIRE(zl_lib); 578 579 return -ENOSYS; 580} 581 582/* 583 * ======== dbll_open ======== 584 */ 585int dbll_open(struct dbll_tar_obj *target, char *file, dbll_flags flags, 586 struct dbll_library_obj **lib_obj) 587{ 588 struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target; 589 struct dbll_library_obj *zl_lib = NULL; 590 s32 err; 591 int status = 0; 592 593 DBC_REQUIRE(refs > 0); 594 DBC_REQUIRE(zl_target); 595 DBC_REQUIRE(zl_target->attrs.fopen != NULL); 596 DBC_REQUIRE(file != NULL); 597 DBC_REQUIRE(lib_obj != NULL); 598 599 zl_lib = zl_target->head; 600 while (zl_lib != NULL) { 601 if (strcmp(zl_lib->file_name, file) == 0) { 602 /* Library is already opened */ 603 zl_lib->open_ref++; 604 break; 605 } 606 zl_lib = zl_lib->next; 607 } 608 if (zl_lib == NULL) { 609 /* Allocate DBL library object */ 610 zl_lib = kzalloc(sizeof(struct dbll_library_obj), GFP_KERNEL); 611 if (zl_lib == NULL) { 612 status = -ENOMEM; 613 } else { 614 zl_lib->ul_pos = 0; 615 /* Increment ref count to allow close on failure 616 * later on */ 617 zl_lib->open_ref++; 618 zl_lib->target_obj = zl_target; 619 /* Keep a copy of the file name */ 620 zl_lib->file_name = kzalloc(strlen(file) + 1, 621 GFP_KERNEL); 622 if (zl_lib->file_name == NULL) { 623 status = -ENOMEM; 624 } else { 625 strncpy(zl_lib->file_name, file, 626 strlen(file) + 1); 627 } 628 zl_lib->sym_tab = NULL; 629 } 630 } 631 /* 632 * Set up objects needed by the dynamic loader 633 */ 634 if (status) 635 goto func_cont; 636 637 /* Stream */ 638 zl_lib->stream.dl_stream.read_buffer = dbll_read_buffer; 639 zl_lib->stream.dl_stream.set_file_posn = dbll_set_file_posn; 640 zl_lib->stream.lib = zl_lib; 641 /* Symbol */ 642 zl_lib->symbol.dl_symbol.add_to_symbol_table = dbll_add_to_symbol_table; 643 zl_lib->symbol.dl_symbol.find_matching_symbol = dbll_find_symbol; 644 zl_lib->symbol.dl_symbol.purge_symbol_table = dbll_purge_symbol_table; 645 zl_lib->symbol.dl_symbol.dload_allocate = allocate; 646 zl_lib->symbol.dl_symbol.dload_deallocate = deallocate; 647 zl_lib->symbol.dl_symbol.error_report = dbll_err_report; 648 zl_lib->symbol.lib = zl_lib; 649 /* Allocate */ 650 zl_lib->allocate.dl_alloc.dload_allocate = dbll_rmm_alloc; 651 zl_lib->allocate.dl_alloc.dload_deallocate = rmm_dealloc; 652 zl_lib->allocate.lib = zl_lib; 653 /* Init */ 654 zl_lib->init.dl_init.connect = connect; 655 zl_lib->init.dl_init.readmem = read_mem; 656 zl_lib->init.dl_init.writemem = write_mem; 657 zl_lib->init.dl_init.fillmem = fill_mem; 658 zl_lib->init.dl_init.execute = execute; 659 zl_lib->init.dl_init.release = release; 660 zl_lib->init.lib = zl_lib; 661 if (!status && zl_lib->fp == NULL) 662 status = dof_open(zl_lib); 663 664 zl_lib->ul_pos = (*(zl_lib->target_obj->attrs.ftell)) (zl_lib->fp); 665 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, (long)0, SEEK_SET); 666 /* Create a hash table for symbols if flag is set */ 667 if (zl_lib->sym_tab != NULL || !(flags & DBLL_SYMB)) 668 goto func_cont; 669 670 zl_lib->sym_tab = 671 gh_create(MAXBUCKETS, sizeof(struct dbll_symbol), name_hash, 672 name_match, sym_delete); 673 if (zl_lib->sym_tab == NULL) { 674 status = -ENOMEM; 675 } else { 676 /* Do a fake load to get symbols - set write func to no_op */ 677 zl_lib->init.dl_init.writemem = no_op; 678 err = dynamic_open_module(&zl_lib->stream.dl_stream, 679 &zl_lib->symbol.dl_symbol, 680 &zl_lib->allocate.dl_alloc, 681 &zl_lib->init.dl_init, 0, 682 &zl_lib->dload_mod_obj); 683 if (err != 0) { 684 status = -EILSEQ; 685 } else { 686 /* Now that we have the symbol table, we can unload */ 687 err = dynamic_unload_module(zl_lib->dload_mod_obj, 688 &zl_lib->symbol.dl_symbol, 689 &zl_lib->allocate.dl_alloc, 690 &zl_lib->init.dl_init); 691 if (err != 0) 692 status = -EILSEQ; 693 694 zl_lib->dload_mod_obj = NULL; 695 } 696 } 697func_cont: 698 if (!status) { 699 if (zl_lib->open_ref == 1) { 700 /* First time opened - insert in list */ 701 if (zl_target->head) 702 (zl_target->head)->prev = zl_lib; 703 704 zl_lib->prev = NULL; 705 zl_lib->next = zl_target->head; 706 zl_target->head = zl_lib; 707 } 708 *lib_obj = (struct dbll_library_obj *)zl_lib; 709 } else { 710 *lib_obj = NULL; 711 if (zl_lib != NULL) 712 dbll_close((struct dbll_library_obj *)zl_lib); 713 714 } 715 DBC_ENSURE((!status && (zl_lib->open_ref > 0) && *lib_obj) 716 || (status && *lib_obj == NULL)); 717 718 dev_dbg(bridge, "%s: target: %p file: %s lib_obj: %p, status 0x%x\n", 719 __func__, target, file, lib_obj, status); 720 721 return status; 722} 723 724/* 725 * ======== dbll_read_sect ======== 726 * Get the content of a COFF section. 727 */ 728int dbll_read_sect(struct dbll_library_obj *lib, char *name, 729 char *buf, u32 size) 730{ 731 struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib; 732 bool opened_doff = false; 733 u32 byte_size; /* size of bytes */ 734 u32 ul_sect_size; /* size of section */ 735 const struct ldr_section_info *sect = NULL; 736 int status = 0; 737 738 DBC_REQUIRE(refs > 0); 739 DBC_REQUIRE(zl_lib); 740 DBC_REQUIRE(name != NULL); 741 DBC_REQUIRE(buf != NULL); 742 DBC_REQUIRE(size != 0); 743 744 /* If DOFF file is not open, we open it. */ 745 if (zl_lib != NULL) { 746 if (zl_lib->fp == NULL) { 747 status = dof_open(zl_lib); 748 if (!status) 749 opened_doff = true; 750 751 } else { 752 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, 753 zl_lib->ul_pos, 754 SEEK_SET); 755 } 756 } else { 757 status = -EFAULT; 758 } 759 if (status) 760 goto func_cont; 761 762 byte_size = 1; 763 if (!dload_get_section_info(zl_lib->desc, name, §)) { 764 status = -ENXIO; 765 goto func_cont; 766 } 767 /* 768 * Ensure the supplied buffer size is sufficient to store 769 * the section buf to be read. 770 */ 771 ul_sect_size = sect->size * byte_size; 772 /* Make sure size is even for good swap */ 773 if (ul_sect_size % 2) 774 ul_sect_size++; 775 776 /* Align size */ 777 ul_sect_size = DOFF_ALIGN(ul_sect_size); 778 if (ul_sect_size > size) { 779 status = -EPERM; 780 } else { 781 if (!dload_get_section(zl_lib->desc, sect, buf)) 782 status = -EBADF; 783 784 } 785func_cont: 786 if (opened_doff) { 787 dof_close(zl_lib); 788 opened_doff = false; 789 } 790 791 dev_dbg(bridge, "%s: lib: %p name: %s buf: %p size: 0x%x, " 792 "status 0x%x\n", __func__, lib, name, buf, size, status); 793 return status; 794} 795 796/* 797 * ======== dbll_set_attrs ======== 798 * Set the attributes of the target. 799 */ 800void dbll_set_attrs(struct dbll_tar_obj *target, struct dbll_attrs *pattrs) 801{ 802 struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target; 803 DBC_REQUIRE(refs > 0); 804 DBC_REQUIRE(zl_target); 805 DBC_REQUIRE(pattrs != NULL); 806 807 if ((pattrs != NULL) && (zl_target != NULL)) 808 zl_target->attrs = *pattrs; 809 810} 811 812/* 813 * ======== dbll_unload ======== 814 */ 815void dbll_unload(struct dbll_library_obj *lib, struct dbll_attrs *attrs) 816{ 817 struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib; 818 s32 err = 0; 819 820 DBC_REQUIRE(refs > 0); 821 DBC_REQUIRE(zl_lib); 822 DBC_REQUIRE(zl_lib->load_ref > 0); 823 dev_dbg(bridge, "%s: lib: %p\n", __func__, lib); 824 zl_lib->load_ref--; 825 /* Unload only if reference count is 0 */ 826 if (zl_lib->load_ref != 0) 827 goto func_end; 828 829 zl_lib->target_obj->attrs = *attrs; 830 if (zl_lib->dload_mod_obj) { 831 err = dynamic_unload_module(zl_lib->dload_mod_obj, 832 &zl_lib->symbol.dl_symbol, 833 &zl_lib->allocate.dl_alloc, 834 &zl_lib->init.dl_init); 835 if (err != 0) 836 dev_dbg(bridge, "%s: failed: 0x%x\n", __func__, err); 837 } 838 /* remove symbols from symbol table */ 839 if (zl_lib->sym_tab != NULL) { 840 gh_delete(zl_lib->sym_tab); 841 zl_lib->sym_tab = NULL; 842 } 843 /* delete DOFF desc since it holds *lots* of host OS 844 * resources */ 845 dof_close(zl_lib); 846func_end: 847 DBC_ENSURE(zl_lib->load_ref >= 0); 848} 849 850/* 851 * ======== dbll_unload_sect ======== 852 * Not supported for COFF. 853 */ 854int dbll_unload_sect(struct dbll_library_obj *lib, char *sec_name, 855 struct dbll_attrs *attrs) 856{ 857 DBC_REQUIRE(refs > 0); 858 DBC_REQUIRE(sec_name != NULL); 859 860 return -ENOSYS; 861} 862 863/* 864 * ======== dof_close ======== 865 */ 866static void dof_close(struct dbll_library_obj *zl_lib) 867{ 868 if (zl_lib->desc) { 869 dload_module_close(zl_lib->desc); 870 zl_lib->desc = NULL; 871 } 872 /* close file */ 873 if (zl_lib->fp) { 874 (zl_lib->target_obj->attrs.fclose) (zl_lib->fp); 875 zl_lib->fp = NULL; 876 } 877} 878 879/* 880 * ======== dof_open ======== 881 */ 882static int dof_open(struct dbll_library_obj *zl_lib) 883{ 884 void *open = *(zl_lib->target_obj->attrs.fopen); 885 int status = 0; 886 887 /* First open the file for the dynamic loader, then open COF */ 888 zl_lib->fp = 889 (void *)((dbll_f_open_fxn) (open)) (zl_lib->file_name, "rb"); 890 891 /* Open DOFF module */ 892 if (zl_lib->fp && zl_lib->desc == NULL) { 893 (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, (long)0, 894 SEEK_SET); 895 zl_lib->desc = 896 dload_module_open(&zl_lib->stream.dl_stream, 897 &zl_lib->symbol.dl_symbol); 898 if (zl_lib->desc == NULL) { 899 (zl_lib->target_obj->attrs.fclose) (zl_lib->fp); 900 zl_lib->fp = NULL; 901 status = -EBADF; 902 } 903 } else { 904 status = -EBADF; 905 } 906 907 return status; 908} 909 910/* 911 * ======== name_hash ======== 912 */ 913static u16 name_hash(void *key, u16 max_bucket) 914{ 915 u16 ret; 916 u16 hash; 917 char *name = (char *)key; 918 919 DBC_REQUIRE(name != NULL); 920 921 hash = 0; 922 923 while (*name) { 924 hash <<= 1; 925 hash ^= *name++; 926 } 927 928 ret = hash % max_bucket; 929 930 return ret; 931} 932 933/* 934 * ======== name_match ======== 935 */ 936static bool name_match(void *key, void *sp) 937{ 938 DBC_REQUIRE(key != NULL); 939 DBC_REQUIRE(sp != NULL); 940 941 if ((key != NULL) && (sp != NULL)) { 942 if (strcmp((char *)key, ((struct dbll_symbol *)sp)->name) == 943 0) 944 return true; 945 } 946 return false; 947} 948 949/* 950 * ======== no_op ======== 951 */ 952static int no_op(struct dynamic_loader_initialize *thisptr, void *bufr, 953 ldr_addr locn, struct ldr_section_info *info, unsigned bytsize) 954{ 955 return 1; 956} 957 958/* 959 * ======== sym_delete ======== 960 */ 961static void sym_delete(void *value) 962{ 963 struct dbll_symbol *sp = (struct dbll_symbol *)value; 964 965 kfree(sp->name); 966} 967 968/* 969 * Dynamic Loader Functions 970 */ 971 972/* dynamic_loader_stream */ 973/* 974 * ======== dbll_read_buffer ======== 975 */ 976static int dbll_read_buffer(struct dynamic_loader_stream *this, void *buffer, 977 unsigned bufsize) 978{ 979 struct dbll_stream *pstream = (struct dbll_stream *)this; 980 struct dbll_library_obj *lib; 981 int bytes_read = 0; 982 983 DBC_REQUIRE(this != NULL); 984 lib = pstream->lib; 985 DBC_REQUIRE(lib); 986 987 if (lib != NULL) { 988 bytes_read = 989 (*(lib->target_obj->attrs.fread)) (buffer, 1, bufsize, 990 lib->fp); 991 } 992 return bytes_read; 993} 994 995/* 996 * ======== dbll_set_file_posn ======== 997 */ 998static int dbll_set_file_posn(struct dynamic_loader_stream *this, 999 unsigned int pos) 1000{ 1001 struct dbll_stream *pstream = (struct dbll_stream *)this; 1002 struct dbll_library_obj *lib; 1003 int status = 0; /* Success */ 1004 1005 DBC_REQUIRE(this != NULL); 1006 lib = pstream->lib; 1007 DBC_REQUIRE(lib); 1008 1009 if (lib != NULL) { 1010 status = (*(lib->target_obj->attrs.fseek)) (lib->fp, (long)pos, 1011 SEEK_SET); 1012 } 1013 1014 return status; 1015} 1016 1017/* dynamic_loader_sym */ 1018 1019/* 1020 * ======== dbll_find_symbol ======== 1021 */ 1022static struct dynload_symbol *dbll_find_symbol(struct dynamic_loader_sym *this, 1023 const char *name) 1024{ 1025 struct dynload_symbol *ret_sym; 1026 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; 1027 struct dbll_library_obj *lib; 1028 struct dbll_sym_val *dbll_sym = NULL; 1029 bool status = false; /* Symbol not found yet */ 1030 1031 DBC_REQUIRE(this != NULL); 1032 lib = ldr_sym->lib; 1033 DBC_REQUIRE(lib); 1034 1035 if (lib != NULL) { 1036 if (lib->target_obj->attrs.sym_lookup) { 1037 /* Check current lib + base lib + dep lib + 1038 * persistent lib */ 1039 status = (*(lib->target_obj->attrs.sym_lookup)) 1040 (lib->target_obj->attrs.sym_handle, 1041 lib->target_obj->attrs.sym_arg, 1042 lib->target_obj->attrs.rmm_handle, name, 1043 &dbll_sym); 1044 } else { 1045 /* Just check current lib for symbol */ 1046 status = dbll_get_addr((struct dbll_library_obj *)lib, 1047 (char *)name, &dbll_sym); 1048 if (!status) { 1049 status = 1050 dbll_get_c_addr((struct dbll_library_obj *) 1051 lib, (char *)name, 1052 &dbll_sym); 1053 } 1054 } 1055 } 1056 1057 if (!status && gbl_search) 1058 dev_dbg(bridge, "%s: Symbol not found: %s\n", __func__, name); 1059 1060 DBC_ASSERT((status && (dbll_sym != NULL)) 1061 || (!status && (dbll_sym == NULL))); 1062 1063 ret_sym = (struct dynload_symbol *)dbll_sym; 1064 return ret_sym; 1065} 1066 1067/* 1068 * ======== find_in_symbol_table ======== 1069 */ 1070static struct dynload_symbol *find_in_symbol_table(struct dynamic_loader_sym 1071 *this, const char *name, 1072 unsigned moduleid) 1073{ 1074 struct dynload_symbol *ret_sym; 1075 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; 1076 struct dbll_library_obj *lib; 1077 struct dbll_symbol *sym; 1078 1079 DBC_REQUIRE(this != NULL); 1080 lib = ldr_sym->lib; 1081 DBC_REQUIRE(lib); 1082 DBC_REQUIRE(lib->sym_tab != NULL); 1083 1084 sym = (struct dbll_symbol *)gh_find(lib->sym_tab, (char *)name); 1085 1086 ret_sym = (struct dynload_symbol *)&sym->value; 1087 return ret_sym; 1088} 1089 1090/* 1091 * ======== dbll_add_to_symbol_table ======== 1092 */ 1093static struct dynload_symbol *dbll_add_to_symbol_table(struct dynamic_loader_sym 1094 *this, const char *name, 1095 unsigned module_id) 1096{ 1097 struct dbll_symbol *sym_ptr = NULL; 1098 struct dbll_symbol symbol; 1099 struct dynload_symbol *dbll_sym = NULL; 1100 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; 1101 struct dbll_library_obj *lib; 1102 struct dynload_symbol *ret; 1103 1104 DBC_REQUIRE(this != NULL); 1105 DBC_REQUIRE(name); 1106 lib = ldr_sym->lib; 1107 DBC_REQUIRE(lib); 1108 1109 /* Check to see if symbol is already defined in symbol table */ 1110 if (!(lib->target_obj->attrs.base_image)) { 1111 gbl_search = false; 1112 dbll_sym = dbll_find_symbol(this, name); 1113 gbl_search = true; 1114 if (dbll_sym) { 1115 redefined_symbol = true; 1116 dev_dbg(bridge, "%s already defined in symbol table\n", 1117 name); 1118 return NULL; 1119 } 1120 } 1121 /* Allocate string to copy symbol name */ 1122 symbol.name = kzalloc(strlen((char *const)name) + 1, GFP_KERNEL); 1123 if (symbol.name == NULL) 1124 return NULL; 1125 1126 if (symbol.name != NULL) { 1127 /* Just copy name (value will be filled in by dynamic loader) */ 1128 strncpy(symbol.name, (char *const)name, 1129 strlen((char *const)name) + 1); 1130 1131 /* Add symbol to symbol table */ 1132 sym_ptr = 1133 (struct dbll_symbol *)gh_insert(lib->sym_tab, (void *)name, 1134 (void *)&symbol); 1135 if (sym_ptr == NULL) 1136 kfree(symbol.name); 1137 1138 } 1139 if (sym_ptr != NULL) 1140 ret = (struct dynload_symbol *)&sym_ptr->value; 1141 else 1142 ret = NULL; 1143 1144 return ret; 1145} 1146 1147/* 1148 * ======== dbll_purge_symbol_table ======== 1149 */ 1150static void dbll_purge_symbol_table(struct dynamic_loader_sym *this, 1151 unsigned module_id) 1152{ 1153 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; 1154 struct dbll_library_obj *lib; 1155 1156 DBC_REQUIRE(this != NULL); 1157 lib = ldr_sym->lib; 1158 DBC_REQUIRE(lib); 1159 1160 /* May not need to do anything */ 1161} 1162 1163/* 1164 * ======== allocate ======== 1165 */ 1166static void *allocate(struct dynamic_loader_sym *this, unsigned memsize) 1167{ 1168 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; 1169 struct dbll_library_obj *lib; 1170 void *buf; 1171 1172 DBC_REQUIRE(this != NULL); 1173 lib = ldr_sym->lib; 1174 DBC_REQUIRE(lib); 1175 1176 buf = kzalloc(memsize, GFP_KERNEL); 1177 1178 return buf; 1179} 1180 1181/* 1182 * ======== deallocate ======== 1183 */ 1184static void deallocate(struct dynamic_loader_sym *this, void *mem_ptr) 1185{ 1186 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; 1187 struct dbll_library_obj *lib; 1188 1189 DBC_REQUIRE(this != NULL); 1190 lib = ldr_sym->lib; 1191 DBC_REQUIRE(lib); 1192 1193 kfree(mem_ptr); 1194} 1195 1196/* 1197 * ======== dbll_err_report ======== 1198 */ 1199static void dbll_err_report(struct dynamic_loader_sym *this, const char *errstr, 1200 va_list args) 1201{ 1202 struct ldr_symbol *ldr_sym = (struct ldr_symbol *)this; 1203 struct dbll_library_obj *lib; 1204 char temp_buf[MAXEXPR]; 1205 1206 DBC_REQUIRE(this != NULL); 1207 lib = ldr_sym->lib; 1208 DBC_REQUIRE(lib); 1209 vsnprintf((char *)temp_buf, MAXEXPR, (char *)errstr, args); 1210 dev_dbg(bridge, "%s\n", temp_buf); 1211} 1212 1213/* dynamic_loader_allocate */ 1214 1215/* 1216 * ======== dbll_rmm_alloc ======== 1217 */ 1218static int dbll_rmm_alloc(struct dynamic_loader_allocate *this, 1219 struct ldr_section_info *info, unsigned align) 1220{ 1221 struct dbll_alloc *dbll_alloc_obj = (struct dbll_alloc *)this; 1222 struct dbll_library_obj *lib; 1223 int status = 0; 1224 u32 mem_sect_type; 1225 struct rmm_addr rmm_addr_obj; 1226 s32 ret = true; 1227 unsigned stype = DLOAD_SECTION_TYPE(info->type); 1228 char *token = NULL; 1229 char *sz_sec_last_token = NULL; 1230 char *sz_last_token = NULL; 1231 char *sz_sect_name = NULL; 1232 char *psz_cur; 1233 s32 token_len = 0; 1234 s32 seg_id = -1; 1235 s32 req = -1; 1236 s32 count = 0; 1237 u32 alloc_size = 0; 1238 u32 run_addr_flag = 0; 1239 1240 DBC_REQUIRE(this != NULL); 1241 lib = dbll_alloc_obj->lib; 1242 DBC_REQUIRE(lib); 1243 1244 mem_sect_type = 1245 (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == 1246 DLOAD_BSS) ? DBLL_BSS : 1247 DBLL_DATA; 1248 1249 /* Attempt to extract the segment ID and requirement information from 1250 the name of the section */ 1251 DBC_REQUIRE(info->name); 1252 token_len = strlen((char *)(info->name)) + 1; 1253 1254 sz_sect_name = kzalloc(token_len, GFP_KERNEL); 1255 sz_last_token = kzalloc(token_len, GFP_KERNEL); 1256 sz_sec_last_token = kzalloc(token_len, GFP_KERNEL); 1257 1258 if (sz_sect_name == NULL || sz_sec_last_token == NULL || 1259 sz_last_token == NULL) { 1260 status = -ENOMEM; 1261 goto func_cont; 1262 } 1263 strncpy(sz_sect_name, (char *)(info->name), token_len); 1264 psz_cur = sz_sect_name; 1265 while ((token = strsep(&psz_cur, ":")) && *token != '\0') { 1266 strncpy(sz_sec_last_token, sz_last_token, 1267 strlen(sz_last_token) + 1); 1268 strncpy(sz_last_token, token, strlen(token) + 1); 1269 token = strsep(&psz_cur, ":"); 1270 count++; /* optimizes processing */ 1271 } 1272 /* If token is 0 or 1, and sz_sec_last_token is DYN_DARAM or DYN_SARAM, 1273 or DYN_EXTERNAL, then mem granularity information is present 1274 within the section name - only process if there are at least three 1275 tokens within the section name (just a minor optimization) */ 1276 if (count >= 3) 1277 strict_strtol(sz_last_token, 10, (long *)&req); 1278 1279 if ((req == 0) || (req == 1)) { 1280 if (strcmp(sz_sec_last_token, "DYN_DARAM") == 0) { 1281 seg_id = 0; 1282 } else { 1283 if (strcmp(sz_sec_last_token, "DYN_SARAM") == 0) { 1284 seg_id = 1; 1285 } else { 1286 if (strcmp(sz_sec_last_token, 1287 "DYN_EXTERNAL") == 0) 1288 seg_id = 2; 1289 } 1290 } 1291 } 1292func_cont: 1293 kfree(sz_sect_name); 1294 sz_sect_name = NULL; 1295 kfree(sz_last_token); 1296 sz_last_token = NULL; 1297 kfree(sz_sec_last_token); 1298 sz_sec_last_token = NULL; 1299 1300 if (mem_sect_type == DBLL_CODE) 1301 alloc_size = info->size + GEM_L1P_PREFETCH_SIZE; 1302 else 1303 alloc_size = info->size; 1304 1305 if (info->load_addr != info->run_addr) 1306 run_addr_flag = 1; 1307 /* TODO - ideally, we can pass the alignment requirement also 1308 * from here */ 1309 if (lib != NULL) { 1310 status = 1311 (lib->target_obj->attrs.alloc) (lib->target_obj->attrs. 1312 rmm_handle, mem_sect_type, 1313 alloc_size, align, 1314 (u32 *) &rmm_addr_obj, 1315 seg_id, req, false); 1316 } 1317 if (status) { 1318 ret = false; 1319 } else { 1320 /* RMM gives word address. Need to convert to byte address */ 1321 info->load_addr = rmm_addr_obj.addr * DSPWORDSIZE; 1322 if (!run_addr_flag) 1323 info->run_addr = info->load_addr; 1324 info->context = (u32) rmm_addr_obj.segid; 1325 dev_dbg(bridge, "%s: %s base = 0x%x len = 0x%x, " 1326 "info->run_addr 0x%x, info->load_addr 0x%x\n", 1327 __func__, info->name, info->load_addr / DSPWORDSIZE, 1328 info->size / DSPWORDSIZE, info->run_addr, 1329 info->load_addr); 1330 } 1331 return ret; 1332} 1333 1334/* 1335 * ======== rmm_dealloc ======== 1336 */ 1337static void rmm_dealloc(struct dynamic_loader_allocate *this, 1338 struct ldr_section_info *info) 1339{ 1340 struct dbll_alloc *dbll_alloc_obj = (struct dbll_alloc *)this; 1341 struct dbll_library_obj *lib; 1342 u32 segid; 1343 int status = 0; 1344 unsigned stype = DLOAD_SECTION_TYPE(info->type); 1345 u32 mem_sect_type; 1346 u32 free_size = 0; 1347 1348 mem_sect_type = 1349 (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == 1350 DLOAD_BSS) ? DBLL_BSS : 1351 DBLL_DATA; 1352 DBC_REQUIRE(this != NULL); 1353 lib = dbll_alloc_obj->lib; 1354 DBC_REQUIRE(lib); 1355 /* segid was set by alloc function */ 1356 segid = (u32) info->context; 1357 if (mem_sect_type == DBLL_CODE) 1358 free_size = info->size + GEM_L1P_PREFETCH_SIZE; 1359 else 1360 free_size = info->size; 1361 if (lib != NULL) { 1362 status = 1363 (lib->target_obj->attrs.free) (lib->target_obj->attrs. 1364 sym_handle, segid, 1365 info->load_addr / 1366 DSPWORDSIZE, free_size, 1367 false); 1368 } 1369} 1370 1371/* dynamic_loader_initialize */ 1372/* 1373 * ======== connect ======== 1374 */ 1375static int connect(struct dynamic_loader_initialize *this) 1376{ 1377 return true; 1378} 1379 1380/* 1381 * ======== read_mem ======== 1382 * This function does not need to be implemented. 1383 */ 1384static int read_mem(struct dynamic_loader_initialize *this, void *buf, 1385 ldr_addr addr, struct ldr_section_info *info, 1386 unsigned nbytes) 1387{ 1388 struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this; 1389 struct dbll_library_obj *lib; 1390 int bytes_read = 0; 1391 1392 DBC_REQUIRE(this != NULL); 1393 lib = init_obj->lib; 1394 DBC_REQUIRE(lib); 1395 /* Need bridge_brd_read function */ 1396 return bytes_read; 1397} 1398 1399/* 1400 * ======== write_mem ======== 1401 */ 1402static int write_mem(struct dynamic_loader_initialize *this, void *buf, 1403 ldr_addr addr, struct ldr_section_info *info, 1404 unsigned bytes) 1405{ 1406 struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this; 1407 struct dbll_library_obj *lib; 1408 struct dbll_tar_obj *target_obj; 1409 struct dbll_sect_info sect_info; 1410 u32 mem_sect_type; 1411 bool ret = true; 1412 1413 DBC_REQUIRE(this != NULL); 1414 lib = init_obj->lib; 1415 if (!lib) 1416 return false; 1417 1418 target_obj = lib->target_obj; 1419 1420 mem_sect_type = 1421 (DLOAD_SECTION_TYPE(info->type) == 1422 DLOAD_TEXT) ? DBLL_CODE : DBLL_DATA; 1423 if (target_obj && target_obj->attrs.write) { 1424 ret = 1425 (*target_obj->attrs.write) (target_obj->attrs.input_params, 1426 addr, buf, bytes, 1427 mem_sect_type); 1428 1429 if (target_obj->attrs.log_write) { 1430 sect_info.name = info->name; 1431 sect_info.sect_run_addr = info->run_addr; 1432 sect_info.sect_load_addr = info->load_addr; 1433 sect_info.size = info->size; 1434 sect_info.type = mem_sect_type; 1435 /* Pass the information about what we've written to 1436 * another module */ 1437 (*target_obj->attrs.log_write) (target_obj->attrs. 1438 log_write_handle, 1439 §_info, addr, 1440 bytes); 1441 } 1442 } 1443 return ret; 1444} 1445 1446/* 1447 * ======== fill_mem ======== 1448 * Fill bytes of memory at a given address with a given value by 1449 * writing from a buffer containing the given value. Write in 1450 * sets of MAXEXPR (128) bytes to avoid large stack buffer issues. 1451 */ 1452static int fill_mem(struct dynamic_loader_initialize *this, ldr_addr addr, 1453 struct ldr_section_info *info, unsigned bytes, unsigned val) 1454{ 1455 bool ret = true; 1456 char *pbuf; 1457 struct dbll_library_obj *lib; 1458 struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this; 1459 1460 DBC_REQUIRE(this != NULL); 1461 lib = init_obj->lib; 1462 pbuf = NULL; 1463 /* Pass the NULL pointer to write_mem to get the start address of Shared 1464 memory. This is a trick to just get the start address, there is no 1465 writing taking place with this Writemem 1466 */ 1467 if ((lib->target_obj->attrs.write) != (dbll_write_fxn) no_op) 1468 write_mem(this, &pbuf, addr, info, 0); 1469 if (pbuf) 1470 memset(pbuf, val, bytes); 1471 1472 return ret; 1473} 1474 1475/* 1476 * ======== execute ======== 1477 */ 1478static int execute(struct dynamic_loader_initialize *this, ldr_addr start) 1479{ 1480 struct dbll_init_obj *init_obj = (struct dbll_init_obj *)this; 1481 struct dbll_library_obj *lib; 1482 bool ret = true; 1483 1484 DBC_REQUIRE(this != NULL); 1485 lib = init_obj->lib; 1486 DBC_REQUIRE(lib); 1487 /* Save entry point */ 1488 if (lib != NULL) 1489 lib->entry = (u32) start; 1490 1491 return ret; 1492} 1493 1494/* 1495 * ======== release ======== 1496 */ 1497static void release(struct dynamic_loader_initialize *this) 1498{ 1499} 1500 1501#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE 1502/** 1503 * find_symbol_context - Basic symbol context structure 1504 * @address: Symbol Adress 1505 * @offset_range: Offset range where the search for the DSP symbol 1506 * started. 1507 * @cur_best_offset: Best offset to start looking for the DSP symbol 1508 * @sym_addr: Address of the DSP symbol 1509 * @name: Symbol name 1510 * 1511 */ 1512struct find_symbol_context { 1513 /* input */ 1514 u32 address; 1515 u32 offset_range; 1516 /* state */ 1517 u32 cur_best_offset; 1518 /* output */ 1519 u32 sym_addr; 1520 char name[120]; 1521}; 1522 1523/** 1524 * find_symbol_callback() - Validates symbol address and copies the symbol name 1525 * to the user data. 1526 * @elem: dsp library context 1527 * @user_data: Find symbol context 1528 * 1529 */ 1530void find_symbol_callback(void *elem, void *user_data) 1531{ 1532 struct dbll_symbol *symbol = elem; 1533 struct find_symbol_context *context = user_data; 1534 u32 symbol_addr = symbol->value.value; 1535 u32 offset = context->address - symbol_addr; 1536 1537 /* 1538 * Address given should be greater than symbol address, 1539 * symbol address should be within specified range 1540 * and the offset should be better than previous one 1541 */ 1542 if (context->address >= symbol_addr && symbol_addr < (u32)-1 && 1543 offset < context->cur_best_offset) { 1544 context->cur_best_offset = offset; 1545 context->sym_addr = symbol_addr; 1546 strncpy(context->name, symbol->name, sizeof(context->name)); 1547 } 1548 1549 return; 1550} 1551 1552/** 1553 * dbll_find_dsp_symbol() - This function retrieves the dsp symbol from the dsp binary. 1554 * @zl_lib: DSP binary obj library pointer 1555 * @address: Given address to find the dsp symbol 1556 * @offset_range: offset range to look for dsp symbol 1557 * @sym_addr_output: Symbol Output address 1558 * @name_output: String with the dsp symbol 1559 * 1560 * This function retrieves the dsp symbol from the dsp binary. 1561 */ 1562bool dbll_find_dsp_symbol(struct dbll_library_obj *zl_lib, u32 address, 1563 u32 offset_range, u32 *sym_addr_output, 1564 char *name_output) 1565{ 1566 bool status = false; 1567 struct find_symbol_context context; 1568 1569 context.address = address; 1570 context.offset_range = offset_range; 1571 context.cur_best_offset = offset_range; 1572 context.sym_addr = 0; 1573 context.name[0] = '\0'; 1574 1575 gh_iterate(zl_lib->sym_tab, find_symbol_callback, &context); 1576 1577 if (context.name[0]) { 1578 status = true; 1579 strcpy(name_output, context.name); 1580 *sym_addr_output = context.sym_addr; 1581 } 1582 1583 return status; 1584} 1585#endif 1586