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/*  ----------------------------------- 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, &sect)) {
 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, &sect)) {
 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                                                        &sect_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 Address
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