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