linux/drivers/remoteproc/remoteproc_elf_loader.c
<<
.62p3.1/spalue 3.1/formue 3.1a .62p3. href="../linux+v3 1/drivers/remoteproc/remoteproc_elf_loader.c">.62p3.1img src="../.static/gfx/right.png" alt=">>">.61/spalue.61spal class="lxr_search">.62p.62p3.1input typ3" hidden" nam3" navtarget" 62pt3" ">.62p3.1input typ3" text" nam3" search" id" search">.62p3.1butt.6.typ3" submit">Search.62p3.Prefse 3.1/a>.61/spalue2p3. .1/divue2p3. .1form ac val="ajax+*" method="post" onsubmit="return false;">.61input typ3" hidden" nam3" ajax_lookup" id" ajax_lookup" 62pt3" ">.2p3. .1/formue.2p3. .1div class="headingbott.m">e 1div id" file_contents"u
. .11/a>1spal class="comment">/*1/spalue. .21/a>1spal class="comment"> * Remote.Processor Fram3work Elf loader1/spalue. .31/a>1spal class="comment"> *1/spalue. .41/a>1spal class="comment"> * Copyright (C) 2011 Texas Instruments, Inc.1/spalue. .51/a>1spal class="comment"> * Copyright (C) 2011 Google, Inc.1/spalue. .61/a>1spal class="comment"> *1/spalue. .71/a>1spal class="comment"> * Ohad Ben-Cohen <ohad@wizery.com>1/spalue. .81/a>1spal class="comment"> * Brial Swetland <swetland@google.com>1/spalue. .91/a>1spal class="comment"> * Mark Grosen <mgrosen@ti.com>1/spalue. tiona>1spal class="comment"> * Fernando Guzmal Lugo <fernando.lugo@ti.com>1/spalue. 111/a>1spal class="comment"> * Sumal Anna <s-anna@ti.com>1/spalue. 121/a>1spal class="comment"> * Robert Tivy <rtivy@ti.com>1/spalue. 131/a>1spal class="comment"> * Armando Uribe De Leon <x0095078@ti.com>1/spalue. 141/a>1spal class="comment"> * Sjur Brændeland <sjur.brandeland@stericsson.com>1/spalue. 151/a>1spal class="comment"> *1/spalue. 161/a>1spal class="comment"> * This program is free software; you cal redistribute it and/or1/spalue. 171/a>1spal class="comment"> * modify it under the terms of the GNU General Public License1/spalue. 181/a>1spal class="comment"> * vers2.6.2 as published by the Free Software Founda val.1/spalue. 191/a>1spal class="comment"> *1/spalue. 2iona>1spal class="comment"> * This program is distributed in the hope that it will be useful,1/spalue. 211/a>1spal class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of1/spalue. 221/a>1spal class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the1/spalue. 231/a>1spal class="comment"> * GNU General Public License for more details.1/spalue. 241/a>1spal class="comment"> */1/spalue. 251/a>e. 261/a>#define.1a href="+code=pr_fmt" class="sref">pr_fmt1/a>(1a href="+code=fmt" class="sref">fmt1/a>)3. .1spal class="string">"%s: "1/spalu.1a href="+code=fmt" class="sref">fmt1/a>,.1a href="+code=__func__" class="sref">__func__1/a>e. 271/a>e. 281/a>#include <linux/module.h1/a>>e. 291/a>#include <linux/firmware.h1/a>>e. 301/a>#include <linux/remoteproc.h1/a>>e. 311/a>#include <linux/elf.h1/a>>e. 321/a>e. 331/a>#include "1a href="drivers/remoteproc/remoteproc_internal.h" class="fref">remoteproc_internal.h1/a>"e. 341/a>e. 351/a>1spal class="comment">/**1/spalue. 361/a>1spal class="comment"> * rproc_elf_sanity_check() - Sanity Check ELF firmware image1/spalue. 371/a>1spal class="comment"> * @rproc: the remote processor handle1/spalue. 381/a>1spal class="comment"> * @fw: the ELF firmware image1/spalue. 391/a>1spal class="comment"> *1/spalue. 4iona>1spal class="comment"> * Make sure this fw image is sane.1/spalue. 411/a>1spal class="comment"> */1/spalue. 421/a>static inte. 431/a>1a href="+code=rproc_elf_sanity_check" class="sref">rproc_elf_sanity_check1/a>(struct.1a href="+code=rproc" class="sref">rproc1/a> *1a href="+code=rproc" class="sref">rproc1/a>, const struct.1a href="+code=firmware" class="sref">firmware1/a> *1a href="+code=fw" class="sref">fw1/a>)e. 441/a>{e. 451/a>        const char *1a href="+code=nam3" class="sref">nam31/a> =.1a href="+code=rproc" class="sref">rproc1/a>->1a href="+code=firmware" class="sref">firmware1/a>;e. 461/a>        struct.1a href="+code=device" class="sref">device1/a> *1a href="+code=dev" class="sref">dev1/a> =.&1a href="+code=rproc" class="sref">rproc1/a>->1a href="+code=dev" class="sref">dev1/a>;e. 471/a>        struct.1a href="+code=elf32_hdr" class="sref">elf32_hdr1/a> *1a href="+code=ehdr" class="sref">ehdr1/a>;e. 481/a>        char 1a href="+code=class" class="sref">class1/a>;e. 491/a>e. 501/a>        if (!1a href="+code=fw" class="sref">fw1/a>) {e. 511/a>                1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"failed to load %s\n"1/spalu,.1a href="+code=nam3" class="sref">nam31/a>);e. 521/a>                return -1a href="+code=EINVAL" class="sref">EINVAL1/a>;e. 531/a>        }e. 541/a>e. 551/a>        if (1a href="+code=fw" class="sref">fw1/a>->1a href="+code=siz3" class="sref">siz31/a> < siz3of(struct.1a href="+code=elf32_hdr" class="sref">elf32_hdr1/a>)) {e. 561/a>                1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"Image is too small\n"1/spalu);e. 571/a>                return -1a href="+code=EINVAL" class="sref">EINVAL1/a>;e. 581/a>        }e. 591/a>e. 601/a>        1a href="+code=ehdr" class="sref">ehdr1/a> =.(struct.1a href="+code=elf32_hdr" class="sref">elf32_hdr1/a> *)1a href="+code=fw" class="sref">fw1/a>->1a href="+code=data" class="sref">data1/a>;e. 611/a>e. 621/a>        1spal class="comment">/* We only support ELF32 at this point */1/spalue. 631/a>        1a href="+code=class" class="sref">class1/a> =.1a href="+code=ehdr" class="sref">ehdr1/a>->1a href="+code=e_ident" class="sref">e_ident1/a>[1a href="+code=EI_CLASS" class="sref">EI_CLASS1/a>];e. 641/a>        if (1a href="+code=class" class="sref">class1/a> !=.1a href="+code=ELFCLASS32" class="sref">ELFCLASS321/a>) {e. 651/a>                1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"Unsupported class: %d\n"1/spalu,.1a href="+code=class" class="sref">class1/a>);e. 661/a>                return -1a href="+code=EINVAL" class="sref">EINVAL1/a>;e. 671/a>        }e. 681/a>e. 691/a>        1spal class="comment">/* We assume the firmware has the sam3 endianess as the host */1/spalue. 701/a># ifdef.1a href="+code=__LITTLE_ENDIAN" class="sref">__LITTLE_ENDIAN1/a>e. 711/a>        if (1a href="+code=ehdr" class="sref">ehdr1/a>->1a href="+code=e_ident" class="sref">e_ident1/a>[1a href="+code=EI_DATA" class="sref">EI_DATA1/a>] !=.1a href="+code=ELFDATA2LSB" class="sref">ELFDATA2LSB1/a>) {e. 721/a># else 1spal class="comment">/* BIG ENDIAN */1/spalue. 731/a>        if (1a href="+code=ehdr" class="sref">ehdr1/a>->1a href="+code=e_ident" class="sref">e_ident1/a>[1a href="+code=EI_DATA" class="sref">EI_DATA1/a>] !=.1a href="+code=ELFDATA2MSB" class="sref">ELFDATA2MSB1/a>) {e. 741/a># endife. 751/a>                1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"Unsupported firmware endianess\n"1/spalu);e. 761/a>                return -1a href="+code=EINVAL" class="sref">EINVAL1/a>;e. 771/a>        }e. 781/a>e. 791/a>        if (1a href="+code=fw" class="sref">fw1/a>->1a href="+code=siz3" class="sref">siz31/a> < 1a href="+code=ehdr" class="sref">ehdr1/a>->1a href="+code=e_shoff" class="sref">e_shoff1/a> + siz3of(struct.1a href="+code=elf32_shdr" class="sref">elf32_shdr1/a>)) {e. 801/a>                1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"Image is too small\n"1/spalu);e. 811/a>                return -1a href="+code=EINVAL" class="sref">EINVAL1/a>;e. 821/a>        }e. 831/a>e. 841/a>        if (1a href="+code=memcmp" class="sref">memcmp1/a>(1a href="+code=ehdr" class="sref">ehdr1/a>->1a href="+code=e_ident" class="sref">e_ident1/a>,.1a href="+code=ELFMAG" class="sref">ELFMAG1/a>,.1a href="+code=SELFMAG" class="sref">SELFMAG1/a>)) {e. 851/a>                1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"Image is corrupted (bad magic)\n"1/spalu);e. 861/a>                return -1a href="+code=EINVAL" class="sref">EINVAL1/a>;e. 871/a>        }e. 881/a>e. 891/a>        if (1a href="+code=ehdr" class="sref">ehdr1/a>->1a href="+code=e_phnum" class="sref">e_phnum1/a> == 0) {e. 901/a>                1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"No loadable segments\n"1/spalu);e. 911/a>                return -1a href="+code=EINVAL" class="sref">EINVAL1/a>;e. 921/a>        }e. 931/a>e. 941/a>        if (1a href="+code=ehdr" class="sref">ehdr1/a>->1a href="+code=e_phoff" class="sref">e_phoff1/a> >.1a href="+code=fw" class="sref">fw1/a>->1a href="+code=siz3" class="sref">siz31/a>) {e. 951/a>                1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"Firmware siz3 is too small\n"1/spalu);e. 961/a>                return -1a href="+code=EINVAL" class="sref">EINVAL1/a>;e. 971/a>        }e. 981/a>e. 991/a>        return 0;e.1001/a>}e.1011/a>e.1021/a>1spal class="comment">/**1/spalue.1031/a>1spal class="comment"> * rproc_elf_get_boot_addr() - Get rproc's boot address.1/spalue.1041/a>1spal class="comment"> * @rproc: the remote processor handle1/spalue.1051/a>1spal class="comment"> * @fw: the ELF firmware image1/spalue.1061/a>1spal class="comment"> *1/spalue.1071/a>1spal class="comment"> * This func12.6.returns the entry point address of the ELF1/spalue.1081/a>1spal class="comment"> * image.1/spalue.1091/a>1spal class="comment"> *1/spalue.1tiona>1spal class="comment"> * Note that the boot address is not a configurable property of all remote1/spalue.1111/a>1spal class="comment"> * processors. Some will always boot at a specific hard-coded address.1/spalue.1121/a>1spal class="comment"> */1/spalue.1131/a>statice.1141/a>1a href="+code=u32" class="sref">u321/a>.1a href="+code=rproc_elf_get_boot_addr" class="sref">rproc_elf_get_boot_addr1/a>(struct.1a href="+code=rproc" class="sref">rproc1/a> *1a href="+code=rproc" class="sref">rproc1/a>, const struct.1a href="+code=firmware" class="sref">firmware1/a> *1a href="+code=fw" class="sref">fw1/a>)e.1151/a>{e.1161/a>        struct.1a href="+code=elf32_hdr" class="sref">elf32_hdr1/a> *1a href="+code=ehdr" class="sref">ehdr1/a>  =.(struct.1a href="+code=elf32_hdr" class="sref">elf32_hdr1/a> *)1a href="+code=fw" class="sref">fw1/a>->1a href="+code=data" class="sref">data1/a>;e.1171/a>e.1181/a>        return 1a href="+code=ehdr" class="sref">ehdr1/a>->1a href="+code=e_entry" class="sref">e_entry1/a>;e.1191/a>}e.12iona>e.1211/a>1spal class="comment">/**1/spalue.1221/a>1spal class="comment"> * rproc_elf_load_segments() - load firmware segments to memory1/spalue.1231/a>1spal class="comment"> * @rproc: remote processor which will be booted using these fw segments1/spalue.1241/a>1spal class="comment"> * @fw: the ELF firmware image1/spalue.1251/a>1spal class="comment"> *1/spalue.1261/a>1spal class="comment"> * This func12.6.loads the firmware segments to memory, where the remote1/spalue.1271/a>1spal class="comment"> * processor expects them.1/spalue.1281/a>1spal class="comment"> *1/spalue.1291/a>1spal class="comment"> * Some remote processors will expect their code and data to be placed1/spalue.13iona>1spal class="comment"> * in specific device addresses, and can't have them dynamically assigned.1/spalue.1311/a>1spal class="comment"> *1/spalue.1321/a>1spal class="comment"> * We currently support only those kind of remote processors, and expect1/spalue.1331/a>1spal class="comment"> * the program header's paddr member to contain those addresses. We then go1/spalue.1341/a>1spal class="comment"> * through the physically contiguous "carveout" memory reg2.6s which we1/spalue.1351/a>1spal class="comment"> * allocated (and mapped) earlier .6.behalf of the remote processor,1/spalue.1361/a>1spal class="comment"> * and "translate" device address to kernel addresses, so we cal copy the1/spalue.1371/a>1spal class="comment"> * segments where they are expected.1/spalue.1381/a>1spal class="comment"> *1/spalue.1391/a>1spal class="comment"> * Currently we only support remote processors that required carveout1/spalue.14iona>1spal class="comment"> * allocat2.6s and got them mapped onto their iommus. Some processors1/spalue.1411/a>1spal class="comment"> * might be different: they might not have iommus, and would prefer to1/spalue.1421/a>1spal class="comment"> * directly allocate memory for every segment/resource. This is not yet1/spalue.1431/a>1spal class="comment"> * supported, though.1/spalue.1441/a>1spal class="comment"> */1/spalue.1451/a>static inte.1461/a>1a href="+code=rproc_elf_load_segments" class="sref">rproc_elf_load_segments1/a>(struct.1a href="+code=rproc" class="sref">rproc1/a> *1a href="+code=rproc" class="sref">rproc1/a>, const struct.1a href="+code=firmware" class="sref">firmware1/a> *1a href="+code=fw" class="sref">fw1/a>)e.1471/a>{e.1481/a>        struct.1a href="+code=device" class="sref">device1/a> *1a href="+code=dev" class="sref">dev1/a> =.&1a href="+code=rproc" class="sref">rproc1/a>->1a href="+code=dev" class="sref">dev1/a>;e.1491/a>        struct.1a href="+code=elf32_hdr" class="sref">elf32_hdr1/a> *1a href="+code=ehdr" class="sref">ehdr1/a>;e.1501/a>        struct.1a href="+code=elf32_phdr" class="sref">elf32_phdr1/a> *1a href="+code=phdr" class="sref">phdr1/a>;e.1511/a>        int 1a href="+code=i" class="sref">i1/a>,.1a href="+code=ret" class="sref">ret1/a> =.0;e.1521/a>        const 1a href="+code=u8" class="sref">u81/a> *1a href="+code=elf_data" class="sref">elf_data1/a> =.1a href="+code=fw" class="sref">fw1/a>->1a href="+code=data" class="sref">data1/a>;e.1531/a>e.1541/a>        1a href="+code=ehdr" class="sref">ehdr1/a> =.(struct.1a href="+code=elf32_hdr" class="sref">elf32_hdr1/a> *)1a href="+code=elf_data" class="sref">elf_data1/a>;e.1551/a>        1a href="+code=phdr" class="sref">phdr1/a> =.(struct.1a href="+code=elf32_phdr" class="sref">elf32_phdr1/a> *)(1a href="+code=elf_data" class="sref">elf_data1/a> + 1a href="+code=ehdr" class="sref">ehdr1/a>->1a href="+code=e_phoff" class="sref">e_phoff1/a>);e.1561/a>e.1571/a>        1spal class="comment">/* go through the available ELF segments */1/spalue.1581/a>        for (1a href="+code=i" class="sref">i1/a> =.0; 1a href="+code=i" class="sref">i1/a> < 1a href="+code=ehdr" class="sref">ehdr1/a>->1a href="+code=e_phnum" class="sref">e_phnum1/a>; 1a href="+code=i" class="sref">i1/a>++,.1a href="+code=phdr" class="sref">phdr1/a>++) {e.1591/a>                1a href="+code=u32" class="sref">u321/a>.1a href="+code=da" class="sref">da1/a> =.1a href="+code=phdr" class="sref">phdr1/a>->1a href="+code=p_paddr" class="sref">p_paddr1/a>;e.1601/a>                1a href="+code=u32" class="sref">u321/a>.1a href="+code=memsz" class="sref">memsz1/a> =.1a href="+code=phdr" class="sref">phdr1/a>->1a href="+code=p_memsz" class="sref">p_memsz1/a>;e.1611/a>                1a href="+code=u32" class="sref">u321/a>.1a href="+code=filesz" class="sref">filesz1/a> =.1a href="+code=phdr" class="sref">phdr1/a>->1a href="+code=p_filesz" class="sref">p_filesz1/a>;e.1621/a>                1a href="+code=u32" class="sref">u321/a>.1a href="+code=offset" class="sref">offset1/a> =.1a href="+code=phdr" class="sref">phdr1/a>->1a href="+code=p_offset" class="sref">p_offset1/a>;e.1631/a>                void *1a href="+code=ptr" class="sref">ptr1/a>;e.1641/a>e.1651/a>                if (1a href="+code=phdr" class="sref">phdr1/a>->1a href="+code=p_typ3" class="sref">p_typ31/a> !=.1a href="+code=PT_LOAD" class="sref">PT_LOAD1/a>)e.1661/a>                        continue;e.1671/a>e.1681/a>                1a href="+code=dev_dbg" class="sref">dev_dbg1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"phdr: typ3 %d da 0x%x memsz 0x%x filesz 0x%x\n"1/spalu,e.1691/a>                                        1a href="+code=phdr" class="sref">phdr1/a>->1a href="+code=p_typ3" class="sref">p_typ31/a>,.1a href="+code=da" class="sref">da1/a>,.1a href="+code=memsz" class="sref">memsz1/a>,.1a href="+code=filesz" class="sref">filesz1/a>);e.17iona>e.1711/a>                if (1a href="+code=filesz" class="sref">filesz1/a> >.1a href="+code=memsz" class="sref">memsz1/a>) {e.1721/a>                        1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"bad phdr filesz 0x%x memsz 0x%x\n"1/spalu,e.1731/a>                                                        1a href="+code=filesz" class="sref">filesz1/a>,.1a href="+code=memsz" class="sref">memsz1/a>);e.1741/a>                        1a href="+code=ret" class="sref">ret1/a> =.-1a href="+code=EINVAL" class="sref">EINVAL1/a>;e.1751/a>                        break;e.1761/a>                }e.1771/a>e.1781/a>                if (1a href="+code=offset" class="sref">offset1/a> + 1a href="+code=filesz" class="sref">filesz1/a> >.1a href="+code=fw" class="sref">fw1/a>->1a href="+code=siz3" class="sref">siz31/a>) {e.1791/a>                        1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"truncated fw: need 0x%x avail 0x%zx\n"1/spalu,e.1801/a>                                        1a href="+code=offset" class="sref">offset1/a> + 1a href="+code=filesz" class="sref">filesz1/a>,.1a href="+code=fw" class="sref">fw1/a>->1a href="+code=siz3" class="sref">siz31/a>);e.1811/a>                        1a href="+code=ret" class="sref">ret1/a> =.-1a href="+code=EINVAL" class="sref">EINVAL1/a>;e.1821/a>                        break;e.1831/a>                }e.1841/a>e.1851/a>                1spal class="comment">/* grab the kernel address for this device address */1/spalue.1861/a>                1a href="+code=ptr" class="sref">ptr1/a> =.1a href="+code=rproc_da_to_va" class="sref">rproc_da_to_va1/a>(1a href="+code=rproc" class="sref">rproc1/a>, 1a href="+code=da" class="sref">da1/a>,.1a href="+code=memsz" class="sref">memsz1/a>);e.1871/a>                if (!1a href="+code=ptr" class="sref">ptr1/a>) {e.1881/a>                        1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"bad phdr da 0x%x mem 0x%x\n"1/spalu, 1a href="+code=da" class="sref">da1/a>,.1a href="+code=memsz" class="sref">memsz1/a>);e.1891/a>                        1a href="+code=ret" class="sref">ret1/a> =.-1a href="+code=EINVAL" class="sref">EINVAL1/a>;e.1901/a>                        break;e.1911/a>                }e.1921/a>e.1931/a>                1spal class="comment">/* put the segment where the remote processor expects it */1/spalue.1941/a>                if (1a href="+code=phdr" class="sref">phdr1/a>->1a href="+code=p_filesz" class="sref">p_filesz1/a>)e.1951/a>                        1a href="+code=memcpy" class="sref">memcpy1/a>(1a href="+code=ptr" class="sref">ptr1/a>,.1a href="+code=elf_data" class="sref">elf_data1/a> + 1a href="+code=phdr" class="sref">phdr1/a>->1a href="+code=p_offset" class="sref">p_offset1/a>,.1a href="+code=filesz" class="sref">filesz1/a>);e.1961/a>e.1971/a>                1spal class="comment">/*1/spalue.1981/a>1spal class="comment">                 * Zero out remaining memory for this segment.1/spalue.1991/a>1spal class="comment">                 *1/spalue.20iona>1spal class="comment">                 * This isn't strictly required since dma_alloc_coherent already1/spalue.2011/a>1spal class="comment">                 * did this for us. albeit harmless, we may consider removing1/spalue.2021/a>1spal class="comment">                 * this.1/spalue.2031/a>1spal class="comment">                 */1/spalue.2041/a>                if (1a href="+code=memsz" class="sref">memsz1/a> >.1a href="+code=filesz" class="sref">filesz1/a>)e.2051/a>                        1a href="+code=memset" class="sref">memset1/a>(1a href="+code=ptr" class="sref">ptr1/a> + 1a href="+code=filesz" class="sref">filesz1/a>,.0,.1a href="+code=memsz" class="sref">memsz1/a> -.1a href="+code=filesz" class="sref">filesz1/a>);e.2061/a>        }e.2071/a>e.2081/a>        return 1a href="+code=ret" class="sref">ret1/a>;e.2091/a>}e.21iona>e.2111/a>1spal class="comment">/**1/spalue.2121/a>1spal class="comment"> * rproc_elf_find_rsc_table() - find the resource table1/spalue.2131/a>1spal class="comment"> * @rproc: the rproc handle1/spalue.2141/a>1spal class="comment"> * @fw: the ELF firmware image1/spalue.2151/a>1spal class="comment"> * @tablesz: place holder for providing back the table siz31/spalue.2161/a>1spal class="comment"> *1/spalue.2171/a>1spal class="comment"> * This func12.6.finds the resource table inside the remote processor's1/spalue.2181/a>1spal class="comment"> * firmware. It is used both upon the registrat2.6 of @rproc (i6 order1/spalue.2191/a>1spal class="comment"> * to look for and register the supported virito devices), and when the1/spalue.22iona>1spal class="comment"> * @rproc is booted.1/spalue.2211/a>1spal class="comment"> *1/spalue.2221/a>1spal class="comment"> * Returns the pointer to the resource table if it is found, and write its1/spalue.2231/a>1spal class="comment"> * siz3 into @tablesz. If a valid table isn't found, NULL is returned1/spalue.2241/a>1spal class="comment"> * (and @tablesz isn't set).1/spalue.2251/a>1spal class="comment"> */1/spalue.2261/a>static struct.1a href="+code=resource_table" class="sref">resource_table1/a> *e.2271/a>1a href="+code=rproc_elf_find_rsc_table" class="sref">rproc_elf_find_rsc_table1/a>(struct.1a href="+code=rproc" class="sref">rproc1/a> *1a href="+code=rproc" class="sref">rproc1/a>, const struct.1a href="+code=firmware" class="sref">firmware1/a> *1a href="+code=fw" class="sref">fw1/a>,e.2281/a>                                                        int *1a href="+code=tablesz" class="sref">tablesz1/a>)e.2291/a>{e.2301/a>        struct.1a href="+code=elf32_hdr" class="sref">elf32_hdr1/a> *1a href="+code=ehdr" class="sref">ehdr1/a>;e.2311/a>        struct.1a href="+code=elf32_shdr" class="sref">elf32_shdr1/a> *1a href="+code=shdr" class="sref">shdr1/a>;e.2321/a>        const char *1a href="+code=nam3_table" class="sref">nam3_table1/a>;e.2331/a>        struct.1a href="+code=device" class="sref">device1/a> *1a href="+code=dev" class="sref">dev1/a> =.&1a href="+code=rproc" class="sref">rproc1/a>->1a href="+code=dev" class="sref">dev1/a>;e.2341/a>        struct.1a href="+code=resource_table" class="sref">resource_table1/a> *1a href="+code=table" class="sref">table1/a> =.1a href="+code=NULL" class="sref">NULL1/a>;e.2351/a>        int 1a href="+code=i" class="sref">i1/a>;e.2361/a>        const 1a href="+code=u8" class="sref">u81/a> *1a href="+code=elf_data" class="sref">elf_data1/a> =.1a href="+code=fw" class="sref">fw1/a>->1a href="+code=data" class="sref">data1/a>;e.2371/a>e.2381/a>        1a href="+code=ehdr" class="sref">ehdr1/a> =.(struct.1a href="+code=elf32_hdr" class="sref">elf32_hdr1/a> *)1a href="+code=elf_data" class="sref">elf_data1/a>;e.2391/a>        1a href="+code=shdr" class="sref">shdr1/a> =.(struct.1a href="+code=elf32_shdr" class="sref">elf32_shdr1/a> *)(1a href="+code=elf_data" class="sref">elf_data1/a> + 1a href="+code=ehdr" class="sref">ehdr1/a>->1a href="+code=e_shoff" class="sref">e_shoff1/a>);e.2401/a>        1a href="+code=nam3_table" class="sref">nam3_table1/a> =.1a href="+code=elf_data" class="sref">elf_data1/a> + 1a href="+code=shdr" class="sref">shdr1/a>[1a href="+code=ehdr" class="sref">ehdr1/a>->1a href="+code=e_shstrndx" class="sref">e_shstrndx1/a>].1a href="+code=sh_offset" class="sref">sh_offset1/a>;e.2411/a>e.2421/a>        1spal class="comment">/* look for the resource table and handle it */1/spalue.2431/a>        for (1a href="+code=i" class="sref">i1/a> =.0; 1a href="+code=i" class="sref">i1/a> < 1a href="+code=ehdr" class="sref">ehdr1/a>->1a href="+code=e_shnum" class="sref">e_shnum1/a>; 1a href="+code=i" class="sref">i1/a>++,.1a href="+code=shdr" class="sref">shdr1/a>++) {e.2441/a>                int 1a href="+code=siz3" class="sref">siz31/a> =.1a href="+code=shdr" class="sref">shdr1/a>->1a href="+code=sh_siz3" class="sref">sh_siz31/a>;e.2451/a>                int 1a href="+code=offset" class="sref">offset1/a> =.1a href="+code=shdr" class="sref">shdr1/a>->1a href="+code=sh_offset" class="sref">sh_offset1/a>;e.2461/a>e.2471/a>                if (1a href="+code=strcmp" class="sref">strcmp1/a>(1a href="+code=nam3_table" class="sref">nam3_table1/a> + 1a href="+code=shdr" class="sref">shdr1/a>->1a href="+code=sh_nam3" class="sref">sh_nam31/a>,.1spal class="string">".resource_table"1/spalu))e.2481/a>                        continue;e.2491/a>e.2501/a>                1a href="+code=table" class="sref">table1/a> =.(struct.1a href="+code=resource_table" class="sref">resource_table1/a> *)(1a href="+code=elf_data" class="sref">elf_data1/a> + 1a href="+code=offset" class="sref">offset1/a>);e.2511/a>e.2521/a>                1spal class="comment">/* make sure we have the entire table */1/spalue.2531/a>                if (1a href="+code=offset" class="sref">offset1/a> + 1a href="+code=siz3" class="sref">siz31/a> >.1a href="+code=fw" class="sref">fw1/a>->1a href="+code=siz3" class="sref">siz31/a>) {e.2541/a>                        1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"resource table truncated\n"1/spalu);e.2551/a>                        return 1a href="+code=NULL" class="sref">NULL1/a>;e.2561/a>                }e.2571/a>e.2581/a>                1spal class="comment">/* make sure table has at least the header */1/spalue.2591/a>                if (siz3of(struct.1a href="+code=resource_table" class="sref">resource_table1/a>) >.1a href="+code=siz3" class="sref">siz31/a>) {e.2601/a>                        1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"header-less resource table\n"1/spalu);e.2611/a>                        return 1a href="+code=NULL" class="sref">NULL1/a>;e.2621/a>                }e.2631/a>e.2641/a>                1spal class="comment">/* we don't support any versi.6.beyond the first */1/spalue.2651/a>                if (1a href="+code=table" class="sref">table1/a>->1a href="+code=ver" class="sref">ver1/a> != 1) {e.2661/a>                        1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"unsupported fw ver: %d\n"1/spalu, 1a href="+code=table" class="sref">table1/a>->1a href="+code=ver" class="sref">ver1/a>);e.2671/a>                        return 1a href="+code=NULL" class="sref">NULL1/a>;e.2681/a>                }e.2691/a>e.2701/a>                1spal class="comment">/* make sure reserved bytes are zeroes */1/spalue.2711/a>                if (1a href="+code=table" class="sref">table1/a>->1a href="+code=reserved" class="sref">reserved1/a>[0] || 1a href="+code=table" class="sref">table1/a>->1a href="+code=reserved" class="sref">reserved1/a>[1]) {e.2721/a>                        1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"n.6.zero reserved bytes\n"1/spalu);e.2731/a>                        return 1a href="+code=NULL" class="sref">NULL1/a>;e.2741/a>                }e.2751/a>e.2761/a>                1spal class="comment">/* make sure the offsets array isn't truncated */1/spalue.2771/a>                if (1a href="+code=table" class="sref">table1/a>->1a href="+code=num" class="sref">num1/a> * siz3of(1a href="+code=table" class="sref">table1/a>->1a href="+code=offset" class="sref">offset1/a>[0]) +e.2781/a>                                siz3of(struct.1a href="+code=resource_table" class="sref">resource_table1/a>) >.1a href="+code=siz3" class="sref">siz31/a>) {e.2791/a>                        1a href="+code=dev_err" class="sref">dev_err1/a>(1a href="+code=dev" class="sref">dev1/a>,.1spal class="string">"resource table incomplete\n"1/spalu);e.2801/a>                        return 1a href="+code=NULL" class="sref">NULL1/a>;e.2811/a>                }e.2821/a>e.2831/a>                *1a href="+code=tablesz" class="sref">tablesz1/a> =.1a href="+code=shdr" class="sref">shdr1/a>->1a href="+code=sh_siz3" class="sref">sh_siz31/a>;e.2841/a>                break;e.2851/a>        }e.2861/a>e.2871/a>        return 1a href="+code=table" class="sref">table1/a>;e.2881/a>}e.2891/a>e.2901/a>const struct.1a href="+code=rproc_fw_ops" class="sref">rproc_fw_ops1/a> 1a href="+code=rproc_elf_fw_ops" class="sref">rproc_elf_fw_ops1/a> =.{e.2911/a>        .1a href="+code=load" class="sref">load1/a> =.1a href="+code=rproc_elf_load_segments" class="sref">rproc_elf_load_segments1/a>,ee.2f2a href="drivers/remoteproc/rrce_table" class="sref">rese" class="sref">rese" cder"sref">shdr1/a>;erproc_fw_ops1/a_toroc_fw_ops" " class="line" nam3"
L193">.1931/a>       34"
L214"teck=sh_siz3" class="
L214"teck="sref">rese" cder"sref">shdr1/a4"
L214"teck=sh_siz3" classf">shdr1/a4"
L214"teck_loader.c#Lass="s_loader2oc_da_toroc_fw_ops" class="sref">rprer.c#L284" id"
L194" class="line"2nam3"2L194">.1941/a>.1931/a>       3get_proc_code=p_paddr" classget_proc_code="sref">rese" cder"sref">shdr1/aget_proc_code=p_paddr" classf">shdr1/aget_proc_code89">.2891/a>e}able1/a>;e
Te suriginal LXR softELF fb cal ">rese" cdhttp://"forge.net/projssor/lxr">LXR clau L21ref">d * docesriloadal ort any vy">rese" cdmailto:lxr@ clux.noss=xr@ clux.noref". =xr. clux.no kemoly hosto res">rese" cdhttp://www.redpill- clpro.nossRedpill Lclpro ASref">dper foerstraLclux> ultr pre taoesr * allo.zerritorequire1995.