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