├── .gitignore ├── .travis.yml ├── Kconfig ├── LICENSE ├── Makefile ├── Notice.md ├── README.md ├── armtz ├── Makefile ├── handle.c ├── handle.h ├── tee_mem.c ├── tee_mem.h ├── tee_smc-arm.S ├── tee_smc-arm64.S ├── tee_tz_drv.c ├── tee_tz_op.h └── tee_tz_priv.h ├── core ├── Makefile ├── tee_context.c ├── tee_core.c ├── tee_core_priv.h ├── tee_debugfs.c ├── tee_debugfs.h ├── tee_kernel_api.c ├── tee_mutex_wait.c ├── tee_mutex_wait.h ├── tee_session.c ├── tee_shm.c ├── tee_shm.h ├── tee_supp_com.c ├── tee_supp_com.h ├── tee_sysfs.c ├── tee_sysfs.h ├── tee_wait_queue.c └── tee_wait_queue.h ├── fdts ├── fvp-foundation-gicv2-psci.dts ├── fvp-foundation-motherboard.dtsi └── readme.txt └── include ├── arm_common ├── optee_msg.h └── optee_smc.h └── linux ├── tee_client_api.h ├── tee_core.h ├── tee_ioc.h └── tee_kernel_api.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.o.cmd 3 | Module.symvers 4 | modules.order 5 | optee.ko 6 | optee.mod.c 7 | .optee.ko.cmd 8 | .tmp_versions 9 | .cproject 10 | Debug 11 | .*.swp 12 | .project 13 | .settings 14 | .optee_armtz.ko.cmd 15 | optee_armtz.ko 16 | optee_armtz.mod.c 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # One may have a look at http://docs.travis-ci.com/user/installing-dependencies/ 2 | 3 | language: c 4 | 5 | notifications: 6 | - email: true 7 | 8 | before_install: 9 | # Install the arm32 cross-compiler 10 | - sudo apt-get update -qq 11 | - sudo apt-get install -y gcc-arm-linux-gnueabihf 12 | - arm-linux-gnueabihf-gcc --version 13 | # Install bc (required by the kernel) 14 | - sudo apt-get install bc 15 | # Install 32-bit compatibility libraries for the Linaro arm64 cross-compiler 16 | # (which is a 32-bit x86 binary) 17 | - if [ `uname -m` = x86_64 ]; then sudo apt-get install libc6-i386 lib32stdc++6 lib32z1; fi 18 | 19 | before_script: 20 | # Store the home repository 21 | - export MYHOME=$PWD 22 | 23 | # Download the arm64 compiler 24 | - wget http://releases.linaro.org/14.08/components/toolchain/binaries/gcc-linaro-aarch64-linux-gnu-4.9-2014.08_linux.tar.xz 25 | - tar xf gcc-linaro-aarch64-linux-gnu-4.9-2014.08_linux.tar.xz 26 | - export PATH=$PATH:$PWD/gcc-linaro-aarch64-linux-gnu-4.9-2014.08_linux/bin 27 | 28 | # Download the kernel 29 | - git clone --depth 1 --branch v4.1-rc1 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 30 | - export DST_KERNEL=$PWD/linux 31 | 32 | script: 33 | # Check coding style 34 | - git format-patch -1 --stdout | $DST_KERNEL/scripts/checkpatch.pl --ignore FILE_PATH_CHANGES --ignore GERRIT_CHANGE_ID - 35 | 36 | # Go in the linux kernel repository 37 | - cd $DST_KERNEL 38 | - git reset --hard v4.1-rc1 39 | 40 | # arm32 compilation 41 | - export ARCH=arm 42 | - export CROSS_COMPILE=arm-linux-gnueabihf- 43 | - echo "CONFIG_MODULES=y" >> arch/arm/configs/multi_v7_defconfig 44 | - echo "CONFIG_MODULE_UNLOAD=y" >> arch/arm/configs/multi_v7_defconfig 45 | - make multi_v7_defconfig 46 | - make -j`getconf _NPROCESSORS_ONLN` zImage 47 | - make -j`getconf _NPROCESSORS_ONLN` M=$MYHOME modules 48 | 49 | # arm64 compilation 50 | - export ARCH=arm64 51 | - export CROSS_COMPILE=aarch64-linux-gnu- 52 | - rm -f .config 53 | - make defconfig 54 | - make -j`getconf _NPROCESSORS_ONLN` all 55 | - make -j`getconf _NPROCESSORS_ONLN` M=$MYHOME modules 56 | 57 | -------------------------------------------------------------------------------- /Kconfig: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2014, STMicroelectronics International N.V. 3 | # 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License Version 2 as 6 | # published by the Free Software Foundation. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | 14 | # Trursted Execution Environment Configuration 15 | config TEE_SUPPORT 16 | bool "Trusted Execution Environment Support" 17 | default y 18 | ---help--- 19 | This implements the Trusted Execution Environment (TEE) Client 20 | API Specification from GlobalPlatform Device Technology. 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | obj-y += core/ 2 | obj-y += armtz/ 3 | -------------------------------------------------------------------------------- /Notice.md: -------------------------------------------------------------------------------- 1 | To avoid duplicating information we link to the Notice.md file in optee_os which 2 | states the contributor agreement rules etc, i.e, optee_linuxdriver follows what 3 | is written in the Notice.md on the URL below 4 | https://github.com/OP-TEE/optee_os/blob/master/Notice.md 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OP-TEE Linux Driver - \*\*DEPRECATED\*\* 2 | 3 | # 2016-04-17: Driver has been deprecated 4 | Since the release of [OP-TEE 2.0.0](https://github.com/OP-TEE/optee_os/blob/master/CHANGELOG.md#op-tee---version-200), 5 | we are no longer using this OP-TEE Linux kernel driver, but we 6 | will keep it here for reference in case anyone needs it for one 7 | or another reason. Also, this version of the OP-TEE driver is 8 | not compatible with OP-TEE 2.0.0 and later. I.e, you cannot use 9 | this with latest on the other OP-TEE gits like optee_os, optee_client, 10 | optee_test etc. 11 | 12 | The new driver we are using is located here: 13 | [linaro-swg/linux/tree/optee](https://github.com/linaro-swg/linux/tree/optee). 14 | Hopefully we will get this driver mainlined at some point in time, 15 | but for the time being that will be our default OP-TEE driver for 16 | OP-TEE >= v2.0.0. 17 | 18 | Besides that we have also backported the 2.0.0 driver to [LSK 3.18](https://git.linaro.org/kernel/linux-linaro-stable.git/shortlog/refs/heads/v3.18/topic/optee) 19 | and [LSK 4.4](https://git.linaro.org/kernel/linux-linaro-stable.git/shortlog/refs/heads/v4.4/topic/optee) 20 | for those that would like to use an older kernel. 21 | 22 | Another important patch that has been mainlined and is needed on older kernels 23 | is the ARM SMCCC patch that could be found here: [14457459f9ca2ff8521686168ea179edc3a56a44] (https://github.com/torvalds/linux/commit/14457459f9ca2ff8521686168ea179edc3a56a44) 24 | 25 | # Description 26 | The optee_linuxdriver git, containing the source code for the TEE driver 27 | module in Linux. 28 | It is distributed under the GPLv2 open-source license. For a general 29 | overview of OP-TEE, please see the [Notice.md](Notice.md) file. 30 | 31 | In this git, the module to build is optee.ko. 32 | It allows communication between the Rich OS Client Application (unsecure 33 | world), the Trusted OS (secure world) and the tee-supplicant (unsecure 34 | world) which is a daemon serving the Trusted OS in secure world with 35 | miscellaneous features, such as file system access. 36 | 37 | ## License 38 | The software is provided under the 39 | [GPL-2.0](http://opensource.org/licenses/GPL-2.0) license. 40 | 41 | ## Platforms supported 42 | This software has hardware dependencies. 43 | The software has been tested using: 44 | 45 | - STMicroelectronics b2020-h416 (orly-2) hardware (32-bits) 46 | - Some initial testing has been done using 47 | [Foundation FVP](http://www.arm.com/fvp), which can be downloaded free of 48 | charge. 49 | 50 | ## Get and build the software 51 | ### Get the compiler 52 | We will strive to use the latest available compiler from Linaro. Start by 53 | downloading and unpacking the compiler. Then export the PATH to the bin folder. 54 | 55 | $ cd $HOME 56 | $ mkdir toolchains 57 | $ cd toolchains 58 | $ wget http://releases.linaro.org/14.05/components/toolchain/binaries/gcc-linaro-arm-linux-gnueabihf-4.9-2014.05_linux.tar.xz 59 | $ tar xvf gcc-linaro-arm-linux-gnueabihf-4.9-2014.05_linux.tar.xz 60 | $ export PATH=$HOME/toolchains/gcc-linaro-arm-linux-gnueabihf-4.9-2014.05_linux/bin:$PATH 61 | 62 | ### Get the Linux kernel (from www.kernel.org) 63 | $ cd $HOME 64 | $ mkdir devel 65 | $ cd devel 66 | $ tar xf linux-3.10.32.tar.xz 67 | $ mv linux-3.10.32 linux 68 | 69 | ### Download the source code 70 | $ cd $HOME 71 | $ cd devel 72 | $ git clone https://github.com/OP-TEE/optee_linuxdriver.git 73 | 74 | ### Build 75 | $ cd $HOME/devel/linux 76 | $ make -j3 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mrproper 77 | $ make -j3 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- defconfig 78 | $ make -j3 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all 79 | $ make -j3 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- M=$HOME/devel/optee_linuxdriver modules 80 | 81 | #### Compiler flags 82 | To be able to see the full command when building you could build using following 83 | flag: 84 | 85 | `$ make V=1` 86 | 87 | ## Coding standards 88 | In this project we are trying to adhere to the same coding convention as used in 89 | the Linux kernel (see 90 | [CodingStyle](https://www.kernel.org/doc/Documentation/CodingStyle)). We achieve this by running 91 | [checkpatch](http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/scripts/checkpatch.pl) from Linux kernel. 92 | However there are a few exceptions that we had to make since the code also 93 | follows GlobalPlatform standards. The exceptions are as follows: 94 | 95 | - CamelCase for GlobalPlatform types are allowed. 96 | - And we also exclude checking third party code that we might use in this 97 | project, such as LibTomCrypt, MPA, newlib (not in this particular git, but 98 | those are also part of the complete TEE solution). The reason for excluding 99 | and not fixing third party code is because we would probably deviate too much 100 | from upstream and therefore it would be hard to rebase against those projects 101 | later on (and we don't expect that it is easy to convince other software 102 | projects to change coding style). 103 | 104 | ### checkpatch 105 | Since checkpatch is licensed under the terms of GNU GPL License Version 2, we 106 | cannot include this script directly into this project. Therefore we have 107 | written the Makefile so you need to explicitly point to the script by exporting 108 | an environment variable, namely CHECKPATCH. So, suppose that the source code for 109 | the Linux kernel is at `$HOME/devel/linux`, then you have to export like follows: 110 | 111 | $ export CHECKPATCH=$HOME/devel/linux/scripts/checkpatch.pl 112 | thereafter it should be possible to use one of the different checkpatch targets 113 | in the [Makefile](Makefile). There are targets for checking all files, checking 114 | against latest commit, against a certain base-commit etc. For the details, read 115 | the [Makefile](Makefile). 116 | -------------------------------------------------------------------------------- /armtz/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ######################################################################### 3 | # Set Internal Variables # 4 | # May be modified to match your setup # 5 | ######################################################################### 6 | CFG_TEE_DRV_DEBUGFS?=0 7 | CFG_TEE_CORE_LOG_LEVEL?=2 8 | CFG_TEE_TA_LOG_LEVEL?=2 9 | 10 | ccflags-y+=-Werror 11 | ccflags-y+=-I$(M)/include/arm_common 12 | ccflags-y+=-I$(M)/include/linux 13 | ccflags-y+=-I$(M)/include 14 | ccflags-y+=-I$(M)/core 15 | 16 | ccflags-y+=-DCFG_TEE_DRV_DEBUGFS=${CFG_TEE_DRV_DEBUGFS} 17 | ccflags-y+=-DCFG_TEE_CORE_LOG_LEVEL=${CFG_TEE_CORE_LOG_LEVEL} 18 | ccflags-y+=-DCFG_TEE_TA_LOG_LEVEL=${CFG_TEE_TA_LOG_LEVEL} 19 | 20 | obj-m += optee_armtz.o 21 | 22 | optee_armtz-objs:= \ 23 | tee_tz_drv.o \ 24 | tee_mem.o \ 25 | handle.o 26 | 27 | 28 | ifeq ($(CONFIG_ARM),y) 29 | # "smc" assembly intruction requires dedicated "armv7 secure extension" 30 | secext := $(call as-instr,.arch_extension sec,+sec) 31 | AFLAGS_tee_smc-arm.o := -Wa,-march=armv7-a$(secext) 32 | optee_armtz-objs += \ 33 | tee_smc-arm.o 34 | endif 35 | 36 | ifeq ($(CONFIG_ARM64),y) 37 | optee_armtz-objs += \ 38 | tee_smc-arm64.o 39 | endif 40 | 41 | -------------------------------------------------------------------------------- /armtz/handle.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Linaro Limited 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #include 14 | #include 15 | #include "handle.h" 16 | 17 | /* 18 | * Define the initial capacity of the database. It should be a low number 19 | * multiple of 2 since some databases a likely to only use a few handles. 20 | * Since the algorithm is to doubles up when growing it shouldn't cause a 21 | * noticable overhead on large databases. 22 | */ 23 | #define HANDLE_DB_INITIAL_MAX_PTRS 4 24 | 25 | void handle_db_destroy(struct handle_db *db) 26 | { 27 | if (db) { 28 | kfree(db->ptrs); 29 | db->ptrs = NULL; 30 | db->max_ptrs = 0; 31 | } 32 | } 33 | 34 | int handle_get(struct handle_db *db, void *ptr) 35 | { 36 | unsigned n; 37 | void *p; 38 | unsigned new_max_ptrs; 39 | 40 | if (!db || !ptr) 41 | return -1; 42 | 43 | /* Try to find an empty location */ 44 | for (n = 0; n < db->max_ptrs; n++) { 45 | if (!db->ptrs[n]) { 46 | db->ptrs[n] = ptr; 47 | return n; 48 | } 49 | } 50 | 51 | /* No location available, grow the ptrs array */ 52 | if (db->max_ptrs) 53 | new_max_ptrs = db->max_ptrs * 2; 54 | else 55 | new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS; 56 | p = krealloc(db->ptrs, new_max_ptrs * sizeof(void *), GFP_KERNEL); 57 | if (!p) 58 | return -1; 59 | db->ptrs = p; 60 | memset(db->ptrs + db->max_ptrs, 0, 61 | (new_max_ptrs - db->max_ptrs) * sizeof(void *)); 62 | db->max_ptrs = new_max_ptrs; 63 | 64 | /* Since n stopped at db->max_ptrs there is an empty location there */ 65 | db->ptrs[n] = ptr; 66 | return n; 67 | } 68 | 69 | void *handle_put(struct handle_db *db, int handle) 70 | { 71 | void *p; 72 | 73 | if (!db || handle < 0 || (unsigned)handle >= db->max_ptrs) 74 | return NULL; 75 | 76 | p = db->ptrs[handle]; 77 | db->ptrs[handle] = NULL; 78 | return p; 79 | } 80 | 81 | void *handle_lookup(struct handle_db *db, int handle) 82 | { 83 | if (!db || handle < 0 || (unsigned)handle >= db->max_ptrs) 84 | return NULL; 85 | 86 | return db->ptrs[handle]; 87 | } 88 | -------------------------------------------------------------------------------- /armtz/handle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Linaro Limited 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #ifndef HANDLE_H 14 | #define HANDLE_H 15 | 16 | struct handle_db { 17 | void **ptrs; 18 | unsigned max_ptrs; 19 | }; 20 | 21 | #define HANDLE_DB_INITIALIZER { NULL, 0 } 22 | 23 | /* 24 | * Frees all internal data structures of the database, but does not free 25 | * the db pointer. The database is safe to reuse after it's destroyed, it 26 | * just be empty again. 27 | */ 28 | void handle_db_destroy(struct handle_db *db); 29 | 30 | /* 31 | * Allocates a new handle and assigns the supplied pointer to it, 32 | * ptr must not be NULL. 33 | * The function returns 34 | * >= 0 on success and 35 | * -1 on failure 36 | */ 37 | int handle_get(struct handle_db *db, void *ptr); 38 | 39 | /* 40 | * Deallocates a handle. Returns the associated pointer of the handle 41 | * the the handle was valid or NULL if it's invalid. 42 | */ 43 | void *handle_put(struct handle_db *db, int handle); 44 | 45 | /* 46 | * Returns the associated pointer of the handle if the handle is a valid 47 | * handle. 48 | * Returns NULL on failure. 49 | */ 50 | void *handle_lookup(struct handle_db *db, int handle); 51 | 52 | #endif /*HANDLE_H*/ 53 | -------------------------------------------------------------------------------- /armtz/tee_mem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | /** 14 | * \file tee_mem.c 15 | * \brief Functions to manage a pool of memory chunks. 16 | * 17 | * This module provides basic functions to manage dynamically a fixed amount 18 | * of memory (memory region). For this current implementation the provided 19 | * memory region used for the allocations should be physically AND logically 20 | * contiguous (only one region is supported for a given allocator). 21 | * 22 | * Principle of the allocator algorithm: "best fit" 23 | * 24 | */ 25 | 26 | #include 27 | 28 | #include "tee_mem.h" 29 | 30 | #define _DUMP_INFO_ALLOCATOR 0 31 | #define USE_DEVM_ALLOC 1 32 | 33 | #ifndef USE_DEVM_ALLOC 34 | #define _KMALLOC(s, f) kmalloc(s, f) 35 | #define _KFREE(a) kfree(a) 36 | #else 37 | #define _KMALLOC(s, f) devm_kzalloc(dev, s, f) 38 | #define _KFREE(a) devm_kfree(dev, a) 39 | #endif 40 | 41 | /** 42 | * \struct mem_chunk 43 | * \brief Elementary descriptor of an allocated memory block 44 | * 45 | * \param node Node for linked list 46 | * \param counter Reference counter 47 | * (0 indicates that the block is not used/freed) 48 | * \param size Total size in bytes 49 | * \param paddr Physical base address 50 | * 51 | * Elementary memory block definition 52 | */ 53 | struct mem_chunk { 54 | struct list_head node; 55 | uint32_t counter; 56 | size_t size; 57 | unsigned long paddr; 58 | }; 59 | 60 | /** 61 | * \struct shm_pool 62 | * \brief Main structure to describe a shared memory pool 63 | * 64 | * \param size Total size in bytes of the associated memory region 65 | * \param vaddr Logical base address 66 | * \param paddr Physical base address 67 | * \param used Total size in bytes of the used memory 68 | * \param mchunks List head for handle the elementary memory blocks 69 | * 70 | * Shared memory pool structure definition 71 | */ 72 | struct shm_pool { 73 | struct mutex lock; 74 | size_t size; /* Size of pool/heap memory segment */ 75 | size_t used; /* Number of bytes allocated */ 76 | void *vaddr; /* Associated Virtual address */ 77 | unsigned long paddr; /* Associated Physical address */ 78 | bool cached; /* true if pool is cacheable */ 79 | struct list_head mchunks; /* Head of memory chunk/block list */ 80 | }; 81 | 82 | #define __CALCULATE_RATIO_MEM_USED(a) (((a->used)*100)/(a->size)) 83 | 84 | /** 85 | * \brief Dumps the information of the shared memory pool 86 | * 87 | * \param pool Pointer on the pool 88 | * \param detailforced Flag to force the log for the detailed informations 89 | * 90 | * Dump/log the meta data of the shared memory pool on the standard output. 91 | * 92 | */ 93 | void tee_shm_pool_dump(struct device *dev, struct shm_pool *pool, bool forced) 94 | { 95 | struct mem_chunk *chunk; 96 | 97 | if (WARN_ON(!dev || !pool)) 98 | return; 99 | 100 | dev_info(dev, 101 | "tee_shm_pool_dump() poolH(0x%p) pAddr=0x%p vAddr=0x%p size=%zu used=%zu(%zu%%)\n", 102 | (void *)pool, 103 | (void *)pool->paddr, 104 | (void *)pool->vaddr, 105 | pool->size, pool->used, __CALCULATE_RATIO_MEM_USED(pool)); 106 | 107 | if ((pool->used != 0) || (forced == true)) { 108 | dev_info(dev, " \\ HEAD next:[0x%p] prev:[0x%p]\n", 109 | (void *)pool->mchunks.next, 110 | (void *)pool->mchunks.prev); 111 | 112 | dev_info(dev, 113 | " |-[@] next prev pAddr size refCount\n"); 114 | 115 | list_for_each_entry(chunk, &pool->mchunks, node) { 116 | dev_info(dev, " | [0x%p] 0x%p 0x%p 0x%p %08zu %d\n", 117 | (void *)chunk, 118 | (void *)chunk->node.next, 119 | (void *)chunk->node.prev, 120 | (void *)chunk->paddr, 121 | chunk->size, chunk->counter); 122 | } 123 | } 124 | } 125 | 126 | bool tee_shm_pool_is_cached(struct shm_pool *pool) 127 | { 128 | return pool->cached; 129 | } 130 | 131 | void tee_shm_pool_set_cached(struct shm_pool *pool) 132 | { 133 | pool->cached = true; 134 | } 135 | 136 | /** 137 | * \brief Creates and returns a new shared memory pool manager structure 138 | * 139 | * \param shm_size Size of the associated memory chunk 140 | * \param shm_vaddr Virtual/logical base address 141 | * \param shm_paddr Physical base address 142 | * 143 | * \return Reference of the created shared memory pool manager 144 | * 145 | * Create and initialize a shared memory pool manager. 146 | * The description of the memory region (shm_size, shm_vaddr, shm_paddr) 147 | * which is passed should be a physically AND virtually contiguous 148 | * (no check is performed by the function). 149 | * If a error is detected returned pool is NULL. 150 | */ 151 | struct shm_pool *tee_shm_pool_create(struct device *dev, size_t shm_size, 152 | void *shm_vaddr, unsigned long shm_paddr) 153 | { 154 | struct mem_chunk *chunk = NULL; 155 | struct shm_pool *pool = NULL; 156 | 157 | if (WARN_ON(!dev)) 158 | goto alloc_failed; 159 | 160 | dev_dbg(dev, "> vaddr=0x%p, paddr=0x%p, size=%zuKiB\n", 161 | shm_vaddr, (void *)shm_paddr, shm_size / 1024); 162 | 163 | /* Alloc and initialize the shm_pool structure */ 164 | pool = _KMALLOC(sizeof(struct shm_pool), GFP_KERNEL); 165 | if (!pool) { 166 | dev_err(dev, "kmalloc failed\n"); 167 | goto alloc_failed; 168 | } 169 | memset(pool, 0, sizeof(*pool)); 170 | mutex_init(&pool->lock); 171 | mutex_lock(&pool->lock); 172 | 173 | INIT_LIST_HEAD(&(pool->mchunks)); 174 | pool->size = shm_size; 175 | pool->vaddr = shm_vaddr; 176 | pool->paddr = shm_paddr; 177 | 178 | /* Create the initial elementary memory chunk */ 179 | /* which handles the whole memory region */ 180 | chunk = _KMALLOC(sizeof(struct mem_chunk), GFP_KERNEL); 181 | if (!chunk) { 182 | dev_err(dev, "kmalloc failed\n"); 183 | goto alloc_failed; 184 | } 185 | memset(chunk, 0, sizeof(*chunk)); 186 | chunk->paddr = shm_paddr; 187 | chunk->size = shm_size; 188 | 189 | /* Adds the new entry immediately after the list head */ 190 | list_add(&(chunk->node), &(pool->mchunks)); 191 | 192 | #if defined(_DUMP_INFO_ALLOCATOR) && (_DUMP_INFO_ALLOCATOR > 0) 193 | tee_shm_pool_dump(dev, pool, true); 194 | #endif 195 | dev_dbg(dev, "< poolH(0x%p) chunkH=0x%p\n", 196 | (void *)(pool), (void *)chunk); 197 | 198 | mutex_unlock(&pool->lock); 199 | return pool; 200 | 201 | alloc_failed: 202 | if (chunk) 203 | _KFREE(chunk); 204 | 205 | if (pool) 206 | _KFREE(pool); 207 | 208 | return NULL; 209 | } 210 | 211 | /** 212 | * Local helper function to check that the physical address is valid 213 | */ 214 | static inline int is_valid_paddr(struct shm_pool *pool, unsigned long paddr) 215 | { 216 | return (paddr >= pool->paddr && paddr < (pool->paddr + pool->size)); 217 | } 218 | 219 | /** 220 | * Local helper function to check that the virtual address is valid 221 | */ 222 | static inline int is_valid_vaddr(struct shm_pool *pool, void *vaddr) 223 | { 224 | return (vaddr >= pool->vaddr && vaddr < (pool->vaddr + pool->size)); 225 | } 226 | 227 | /** 228 | * \brief Destroy the shared memory pool manager 229 | * 230 | * \param pool Pointer on the pool 231 | * 232 | * Destroy a memory pool manager 233 | * 234 | */ 235 | void tee_shm_pool_destroy(struct device *dev, struct shm_pool *pool) 236 | { 237 | struct mem_chunk *chunk; 238 | 239 | if (WARN_ON(!dev || !pool)) 240 | return; 241 | 242 | dev_dbg(dev, "> poolH(0x%p)\n", (void *)pool); 243 | 244 | #if defined(_DUMP_INFO_ALLOCATOR) && (_DUMP_INFO_ALLOCATOR > 0) 245 | tee_shm_pool_dump(dev, pool, true); 246 | #endif 247 | 248 | tee_shm_pool_reset(dev, pool); 249 | 250 | chunk = list_first_entry(&pool->mchunks, struct mem_chunk, node); 251 | dev_dbg(dev, "free chunkH=0x%p\n", (void *)chunk); 252 | _KFREE(chunk); 253 | _KFREE(pool); 254 | 255 | dev_dbg(dev, "<\n"); 256 | } 257 | 258 | /** 259 | * \brief Free all reserved chunk if any, and set pool at it initial state 260 | * 261 | * \param pool Pointer on the pool 262 | * 263 | */ 264 | void tee_shm_pool_reset(struct device *dev, struct shm_pool *pool) 265 | { 266 | struct mem_chunk *chunk; 267 | struct mem_chunk *tmp; 268 | struct mem_chunk *first = NULL; 269 | 270 | if (WARN_ON(!dev || !pool)) 271 | return; 272 | 273 | mutex_lock(&pool->lock); 274 | 275 | list_for_each_entry_safe(chunk, tmp, &pool->mchunks, node) { 276 | if (first != NULL) { 277 | dev_err(dev, "Free lost chunkH=0x%p\n", (void *)chunk); 278 | list_del(&chunk->node); 279 | _KFREE(chunk); 280 | } else { 281 | first = chunk; 282 | } 283 | } 284 | 285 | first->counter = 0; 286 | first->paddr = pool->paddr; 287 | first->size = pool->size; 288 | pool->used = 0; 289 | 290 | mutex_unlock(&pool->lock); 291 | } 292 | 293 | /** 294 | * \brief Return the logical address 295 | * 296 | * \param pool Pointer on the pool 297 | * \param paddr Physical address 298 | * 299 | * \return Virtual/logical address 300 | * 301 | * Return the associated virtual/logical address. The address should be inside 302 | * the range of addresses managed by the shm pool. 303 | * 304 | */ 305 | void *tee_shm_pool_p2v(struct device *dev, struct shm_pool *pool, 306 | unsigned long paddr) 307 | { 308 | if (WARN_ON(!dev || !pool)) 309 | return NULL; 310 | 311 | mutex_lock(&pool->lock); 312 | if (!is_valid_paddr(pool, paddr)) { 313 | mutex_unlock(&pool->lock); 314 | dev_err(dev, 315 | "tee_shm_pool_p2v() paddr=0x%p not in the shm pool\n", 316 | (void *)paddr); 317 | return NULL; 318 | } else { 319 | unsigned long offset = paddr - pool->paddr; 320 | void *p = (void *)((unsigned long)pool->vaddr + offset); 321 | 322 | mutex_unlock(&pool->lock); 323 | return p; 324 | } 325 | } 326 | 327 | /** 328 | * \brief Return the physical address 329 | * 330 | * \param pool Pointer on the pool 331 | * \param vaddr Logical/Virtual address 332 | * 333 | * \return Physical address 334 | * 335 | * Return the associated physical address. The address should be inside 336 | * the range of addresses managed by the pool. 337 | * 338 | */ 339 | unsigned long tee_shm_pool_v2p(struct device *dev, struct shm_pool *pool, 340 | void *vaddr) 341 | { 342 | if (WARN_ON(!dev || !pool)) 343 | return 0UL; 344 | 345 | mutex_lock(&pool->lock); 346 | if (!is_valid_vaddr(pool, vaddr)) { 347 | dev_err(dev, 348 | "tee_shm_pool_v2p() vaddr=0x%p not in shm pool\n", 349 | (void *)vaddr); 350 | mutex_unlock(&pool->lock); 351 | return 0UL; 352 | } else { 353 | unsigned long offset = vaddr - pool->vaddr; 354 | unsigned long p = pool->paddr + offset; 355 | 356 | mutex_unlock(&pool->lock); 357 | return p; 358 | } 359 | } 360 | 361 | /** 362 | * \brief Allocate a new block of memory 363 | * 364 | * \param pool Pointer on the pool 365 | * \param size Expected size (in byte) 366 | * \param alignment Alignment constraint (in byte) 367 | * 368 | * \return Physical base address of the allocated block 369 | * 370 | * Allocate a memory chunk inside the memory region managed by the pool. 371 | * 372 | */ 373 | unsigned long tee_shm_pool_alloc(struct device *dev, 374 | struct shm_pool *pool, 375 | size_t size, size_t alignment) 376 | { 377 | struct mem_chunk *chunk; 378 | struct mem_chunk *betterchunk = NULL; 379 | struct mem_chunk *prev_chunk = NULL; 380 | struct mem_chunk *next_chunk = NULL; 381 | unsigned long begAddr; 382 | unsigned long endAddr; 383 | 384 | if (WARN_ON(!dev || !pool)) 385 | return 0UL; 386 | 387 | dev_dbg(dev, "> poolH(%p:%p:%x) size=0x%zx align=0x%zx\n", 388 | pool, (void *)pool->paddr, (unsigned int)pool->size, size, 389 | alignment); 390 | 391 | /* Align on cache line of the target */ 392 | /* \todo(jmd) Should be defined by a global target specific parameter */ 393 | /* size = (size + (32-1)) & ~(32-1) */ 394 | 395 | if (ALIGN(size, 0x20) < size) 396 | goto failed_out; 397 | 398 | if (alignment == 0) 399 | alignment = 1; 400 | 401 | size = ALIGN(size, 0x20); 402 | 403 | alignment = ALIGN(alignment, 0x20); 404 | 405 | if (size > (pool->size - pool->used)) 406 | goto failed_out; 407 | 408 | mutex_lock(&pool->lock); 409 | 410 | /** 411 | * Algorithm: Smallest waste (best fit): We choose the block that has the 412 | * smallest waste. In other words we choose the block so that 413 | * size(b) - size is as small as possible. 414 | */ 415 | list_for_each_entry(chunk, &pool->mchunks, node) { 416 | if (chunk->counter == 0) { /* Free chunk */ 417 | begAddr = ALIGN(chunk->paddr, alignment); 418 | endAddr = begAddr + size; 419 | 420 | if (begAddr >= chunk->paddr 421 | && endAddr <= (chunk->paddr + chunk->size) 422 | && (betterchunk == NULL 423 | /* Always split smaller block */ 424 | || chunk->size < betterchunk->size)) 425 | betterchunk = chunk; 426 | } 427 | } 428 | 429 | /** 430 | * Update the linked list 431 | */ 432 | if (betterchunk != NULL) { 433 | prev_chunk = _KMALLOC(sizeof(struct mem_chunk), GFP_KERNEL); 434 | next_chunk = _KMALLOC(sizeof(struct mem_chunk), GFP_KERNEL); 435 | 436 | if ((!prev_chunk) || (!next_chunk)) 437 | goto failed_out_unlock; 438 | 439 | begAddr = ALIGN(betterchunk->paddr, alignment); 440 | endAddr = begAddr + size; 441 | 442 | if (betterchunk->paddr < begAddr) { 443 | /* memory between begin of chunk and begin 444 | * of created memory => create a free chunk */ 445 | prev_chunk->counter = 0; 446 | prev_chunk->paddr = betterchunk->paddr; 447 | prev_chunk->size = begAddr - betterchunk->paddr; 448 | 449 | betterchunk->paddr = begAddr; 450 | betterchunk->size -= prev_chunk->size; 451 | 452 | dev_dbg(dev, 453 | "create p_chunkH=0x%p paddr=0x%p (s=%zu)\n", 454 | (void *)prev_chunk, 455 | (void *)prev_chunk->paddr, prev_chunk->size); 456 | 457 | list_add_tail(&(prev_chunk->node), 458 | &(betterchunk->node)); 459 | prev_chunk = NULL; 460 | } else { 461 | _KFREE(prev_chunk); 462 | } 463 | 464 | if (betterchunk->paddr + betterchunk->size > endAddr) { 465 | /* memory between end of chunk and end of 466 | * created memory => create a free chunk */ 467 | next_chunk->counter = 0; 468 | next_chunk->paddr = endAddr; 469 | next_chunk->size = betterchunk->size - size; 470 | 471 | dev_dbg(dev, 472 | "create n_chunkH=0x%p paddr=0x%p (s=%zu)\n", 473 | (void *)next_chunk, 474 | (void *)next_chunk->paddr, next_chunk->size); 475 | 476 | betterchunk->size = size; 477 | 478 | list_add(&(next_chunk->node), &(betterchunk->node)); 479 | next_chunk = NULL; 480 | } else { 481 | _KFREE(next_chunk); 482 | } 483 | 484 | betterchunk->counter = 1; 485 | pool->used += size; 486 | 487 | mutex_unlock(&pool->lock); 488 | 489 | #if defined(_DUMP_INFO_ALLOCATOR) && (_DUMP_INFO_ALLOCATOR > 1) 490 | tee_shm_pool_dump(dev, pool, false); 491 | #endif 492 | 493 | dev_dbg(dev, 494 | "< chunkH=0x%p paddr=%p (s=%zu) align=0x%zx\n", 495 | (void *)betterchunk, 496 | (void *)betterchunk->paddr, 497 | betterchunk->size, alignment); 498 | 499 | return betterchunk->paddr; 500 | } 501 | 502 | failed_out_unlock: 503 | mutex_unlock(&pool->lock); 504 | failed_out: 505 | if (prev_chunk) 506 | _KFREE(prev_chunk); 507 | if (next_chunk) 508 | _KFREE(next_chunk); 509 | 510 | dev_err(dev, 511 | "tee_shm_pool_alloc() FAILED, size=0x%zx, align=0x%zx free=%zu\n", 512 | size, alignment, pool->size - pool->used); 513 | 514 | #if defined(_DUMP_INFO_ALLOCATOR) && (_DUMP_INFO_ALLOCATOR > 1) 515 | tee_shm_pool_dump(dev, pool, true); 516 | #endif 517 | 518 | return 0UL; 519 | } 520 | 521 | /** 522 | * \brief Release a allocated block of memory 523 | * 524 | * \param pool Pointer on the pool 525 | * \param paddr Physical @ of the block which must be released 526 | * \param size Reference to return the size of the block 527 | * 528 | * Free a allocated memory block inside 529 | * the memory region managed by the pool. 530 | * 531 | */ 532 | int tee_shm_pool_free(struct device *dev, struct shm_pool *pool, 533 | unsigned long paddr, size_t *size) 534 | { 535 | struct mem_chunk *chunk; 536 | 537 | if (WARN_ON(!dev || !pool)) 538 | return -EINVAL; 539 | 540 | dev_dbg(dev, "> Try to free ... poolH(0x%p) paddr=0x%p\n", 541 | (void *)pool, (void *)paddr); 542 | 543 | #if defined(_DUMP_INFO_ALLOCATOR) && (_DUMP_INFO_ALLOCATOR > 1) 544 | tee_shm_pool_dump(dev, pool, false); 545 | #endif 546 | 547 | mutex_lock(&pool->lock); 548 | 549 | if (!is_valid_paddr(pool, paddr)) 550 | goto out_failed; 551 | 552 | list_for_each_entry(chunk, &pool->mchunks, node) { 553 | if (chunk->paddr == paddr) { 554 | if (size != NULL) 555 | *size = chunk->size; 556 | 557 | if (chunk->counter == 0) { 558 | dev_warn(dev, 559 | "< tee_shm_pool_free() WARNING, paddr=0x%p already released\n", 560 | (void *)paddr); 561 | return -EINVAL; 562 | } else if (--chunk->counter == 0) { 563 | dev_dbg(dev, "paddr=%p\n", (void *)paddr); 564 | 565 | pool->used -= chunk->size; 566 | 567 | /* Merge with previous */ 568 | if (chunk->node.prev != &pool->mchunks) { 569 | struct mem_chunk *prev = 570 | list_entry(chunk->node.prev, 571 | struct mem_chunk, node); 572 | if (prev->counter == 0) { 573 | dev_dbg(dev, 574 | "chunkH=0x%p paddr=0x%p free ok\n", 575 | (void *)chunk, 576 | (void *)paddr); 577 | prev->size += chunk->size; 578 | list_del(&chunk->node); 579 | _KFREE(chunk); 580 | chunk = prev; 581 | } 582 | } 583 | /* Merge with next */ 584 | if (chunk->node.next != &pool->mchunks) { 585 | struct mem_chunk *next = 586 | list_entry(chunk->node.next, 587 | struct mem_chunk, node); 588 | if (next->counter == 0) { 589 | dev_dbg(dev, 590 | "chunkH=0x%p paddr=0x%p free ok\n", 591 | (void *)chunk, 592 | (void *)paddr); 593 | chunk->size += next->size; 594 | list_del(&next->node); 595 | _KFREE(next); 596 | } 597 | } 598 | mutex_unlock(&pool->lock); 599 | 600 | #if defined(_DUMP_INFO_ALLOCATOR) && (_DUMP_INFO_ALLOCATOR > 1) 601 | tee_shm_pool_dump(dev, pool, false); 602 | #endif 603 | dev_dbg(dev, "< freed\n"); 604 | return 0; 605 | 606 | } else { 607 | mutex_unlock(&pool->lock); 608 | dev_dbg(dev, 609 | "< paddr=0x%p (--) refcounter is decremented ret=1\n", 610 | (void *)paddr); 611 | return 1; 612 | } 613 | } 614 | } 615 | 616 | out_failed: 617 | mutex_unlock(&pool->lock); 618 | #if defined(_DUMP_INFO_ALLOCATOR) && (_DUMP_INFO_ALLOCATOR > 1) 619 | tee_shm_pool_dump(dev, pool, false); 620 | #endif 621 | dev_err(dev, 622 | "< tee_shm_pool_free() FAILED, pAddr=0x%p not found\n", 623 | (void *)paddr); 624 | return -EINVAL; 625 | } 626 | 627 | /** 628 | * \brief Increase the reference count of the memory chunk 629 | * 630 | * \param pool Pointer on the pool 631 | * \param paddr Physical address 632 | * 633 | * \return true if successful (false otherwise) 634 | * 635 | * Increment the reference count of the allocated block of memory. 636 | * paddr should a valid address returned by the tee_shm_pool_alloc(). 637 | * 638 | */ 639 | bool tee_shm_pool_incref(struct device *dev, struct shm_pool *pool, 640 | unsigned long paddr) 641 | { 642 | struct mem_chunk *chunk; 643 | 644 | if (WARN_ON(!dev || !pool)) 645 | return false; 646 | 647 | mutex_lock(&pool->lock); 648 | 649 | if (!is_valid_paddr(pool, paddr)) 650 | goto out_failed; 651 | 652 | list_for_each_entry(chunk, &pool->mchunks, node) { 653 | if (chunk->paddr == paddr) { 654 | dev_dbg(dev, 655 | "pAddr=%p (++) refcounter is incremented\n", 656 | (void *)paddr); 657 | chunk->counter++; 658 | 659 | #if defined(_DUMP_INFO_ALLOCATOR) && (_DUMP_INFO_ALLOCATOR > 0) 660 | tee_shm_pool_dump(dev, pool, false); 661 | #endif 662 | mutex_unlock(&pool->lock); 663 | return true; 664 | } 665 | } 666 | 667 | out_failed: 668 | mutex_unlock(&pool->lock); 669 | 670 | dev_err(dev, 671 | "tee_shm_pool_incref() FAILED, pAddr=%p is not a valid @\n", 672 | (void *)paddr); 673 | 674 | return false; 675 | } 676 | -------------------------------------------------------------------------------- /armtz/tee_mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #ifndef TEE_MEM_H 14 | #define TEE_MEM_H 15 | 16 | #include 17 | #include 18 | 19 | struct shm_pool; 20 | 21 | struct shm_pool *tee_shm_pool_create(struct device *dev, size_t shm_size, 22 | void *shm_vaddr, unsigned long shm_paddr); 23 | 24 | void tee_shm_pool_destroy(struct device *dev, struct shm_pool *pool); 25 | 26 | void *tee_shm_pool_p2v(struct device *dev, struct shm_pool *pool, 27 | unsigned long paddr); 28 | 29 | unsigned long tee_shm_pool_v2p(struct device *dev, struct shm_pool *pool, 30 | void *vaddr); 31 | 32 | unsigned long tee_shm_pool_alloc(struct device *dev, 33 | struct shm_pool *pool, 34 | size_t size, size_t alignment); 35 | 36 | int tee_shm_pool_free(struct device *dev, struct shm_pool *pool, 37 | unsigned long paddr, size_t *size); 38 | 39 | bool tee_shm_pool_incref(struct device *dev, struct shm_pool *pool, 40 | unsigned long paddr); 41 | 42 | void tee_shm_pool_dump(struct device *dev, struct shm_pool *pool, bool forced); 43 | 44 | void tee_shm_pool_reset(struct device *dev, struct shm_pool *pool); 45 | 46 | bool tee_shm_pool_is_cached(struct shm_pool *pool); 47 | 48 | void tee_shm_pool_set_cached(struct shm_pool *pool); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /armtz/tee_smc-arm.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #include 14 | 15 | .text 16 | .balign 4 17 | .code 32 18 | 19 | /* void tee_smc_call(struct smc_param *param); */ 20 | .globl tee_smc_call 21 | ENTRY(tee_smc_call) 22 | push {r4-r8, lr} 23 | mov r8, r0 24 | ldm r8, {r0-r7} 25 | .arch_extension sec 26 | smc #0 27 | stm r8, {r0-r7} 28 | pop {r4-r8, pc} 29 | ENDPROC(tee_smc_call) 30 | -------------------------------------------------------------------------------- /armtz/tee_smc-arm64.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Linaro Limited 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #include 14 | 15 | .text 16 | 17 | #define SMC_PARAM_W0_OFFS 0 18 | #define SMC_PARAM_W2_OFFS 8 19 | #define SMC_PARAM_W4_OFFS 16 20 | #define SMC_PARAM_W6_OFFS 24 21 | 22 | /* void tee_smc_call(struct smc_param *param); */ 23 | .globl tee_smc_call 24 | ENTRY(tee_smc_call) 25 | stp x28, x30, [sp, #-16]! 26 | mov x28, x0 27 | ldp w0, w1, [x28, #SMC_PARAM_W0_OFFS] 28 | ldp w2, w3, [x28, #SMC_PARAM_W2_OFFS] 29 | ldp w4, w5, [x28, #SMC_PARAM_W4_OFFS] 30 | ldp w6, w7, [x28, #SMC_PARAM_W6_OFFS] 31 | smc #0 32 | stp w0, w1, [x28, #SMC_PARAM_W0_OFFS] 33 | stp w2, w3, [x28, #SMC_PARAM_W2_OFFS] 34 | ldp x28, x30, [sp], #16 35 | ret 36 | ENDPROC(tee_smc_call) 37 | -------------------------------------------------------------------------------- /armtz/tee_tz_op.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #ifndef __TEE_ARMV7_OP_H__ 14 | #define __TEE_ARMV7_OP_H__ 15 | 16 | enum t_issw_service_id { 17 | /* 18 | * ("SSAPI_PRE_INIT_SERV") 19 | */ 20 | SSAPI_PRE_INIT_SERV = 1, 21 | 22 | /* 23 | * ("SSAPI_POST_SPEEDUP_INIT_SERV") 24 | * Reserved, Not used 25 | */ 26 | SSAPI_POST_SPEEDUP_INIT_SERV = 2, 27 | 28 | /* 29 | * ("SSAPI_ISSW_IMPORT_SERV") 30 | */ 31 | SSAPI_ISSW_IMPORT_SERV = 3, 32 | 33 | /* 34 | * ("SSAPI_RET_FROM_INT_SERV") 35 | */ 36 | SSAPI_RET_FROM_INT_SERV = 4, 37 | 38 | /* 39 | * ("SSAPI_RET_FROM_RPC_SERV") 40 | */ 41 | SSAPI_RET_FROM_RPC_SERV = 5, 42 | 43 | /* 44 | * "ISSWAPI_ISSW_EXECUTE_SERV" is linked to ROM code 45 | * ("SSAPI_ISSW_EXECUTE_SERV") 46 | */ 47 | ISSWAPI_ISSW_EXECUTE_SERV = 6, 48 | ISSWAPI_PROT_APPL_MSG_SEND = 0x10000000, 49 | ISSWAPI_EXTERNAL_CODE_CHECK = 0x10000001, 50 | ISSWAPI_SECURE_LOAD = 0x10000002, 51 | ISSWAPI_ISSW_REIMPORT_PUB_KEYS = 0x10000003, 52 | 53 | /* Accessible only on request */ 54 | ISSWAPI_WRITE_L2CC = 0x10000004, 55 | ISSWAPI_WRITE_CP15_SCTLR = 0x10000005, 56 | ISSWAPI_READ_CP15_SCTLR = 0x10000006, 57 | ISSWAPI_WRITE_CP15_ACTLR = 0x10000007, 58 | ISSWAPI_READ_CP15_ACTLR = 0x10000008, 59 | ISSWAPI_WRITE_CP15_DIAGR = 0x10000009, 60 | ISSWAPI_READ_CP15_DIAGR = 0x1000000A, 61 | 62 | ISSWAPI_EXECUTE_TA = 0x11000001, 63 | ISSWAPI_CLOSE_TA = 0x11000002, 64 | ISSWAPI_FLUSH_BOOT_CODE = 0x11000003, 65 | /* Generic, restricted to be used by u-boot */ 66 | ISSWAPI_VERIFY_SIGNED_HEADER = 0x11000005, 67 | ISSWAPI_VERIFY_HASH = 0x11000006, 68 | /* 8500 only, restricted to be used by u-boot */ 69 | ISSWAPI_GET_RT_FLAGS = 0x11000007, 70 | 71 | /* For TEE Client API 1.0 */ 72 | ISSWAPI_TEEC_OPEN_SESSION = 0x11000008, 73 | ISSWAPI_TEEC_CLOSE_SESSION = 0x11000009, 74 | ISSWAPI_TEEC_INVOKE_COMMAND = 0x1100000a, 75 | ISSWAPI_REGISTER_RPC = 0x1100000b, /* this is NOT a GP TEE API ! */ 76 | ISSWAPI_SET_SEC_DDR = 0x1100000c, /* this is NOT a GP TEE API ! */ 77 | ISSWAPI_TEEC_CANCEL_COMMAND = 0x1100000d, 78 | ISSWAPI_TEEC_REGISTER_MEMORY = 0x1100000e, 79 | ISSWAPI_TEEC_UNREGISTER_MEMORY = 0x1100000f, 80 | 81 | /* Internal command */ 82 | ISSWAPI_TEE_DEINIT_CPU = 0x11000010, 83 | ISSWAPI_TEE_CRASH_CPU = 0x11000011, 84 | ISSWAPI_TEE_SET_CORE_TRACE_LEVEL = 0x11000012, 85 | ISSWAPI_TEE_GET_CORE_TRACE_LEVEL = 0x11000013, 86 | ISSWAPI_TEE_SET_TA_TRACE_LEVEL = 0x11000014, 87 | ISSWAPI_TEE_GET_TA_TRACE_LEVEL = 0x11000015, 88 | ISSWAPI_TEE_GET_CORE_STATUS = 0x11000016, 89 | ISSWAPI_TEE_FLUSH_CACHE = 0x11000017, 90 | 91 | ISSWAPI_REGISTER_DEF_SHM = 0x11000020, 92 | ISSWAPI_UNREGISTER_DEF_SHM = 0x11000021, 93 | ISSWAPI_REGISTER_IRQFWD = 0x11000022, 94 | ISSWAPI_UNREGISTER_IRQFWD = 0x11000023, 95 | ISSWAPI_GET_SHM_START = 0x11000024, 96 | ISSWAPI_GET_SHM_SIZE = 0x11000025, 97 | ISSWAPI_GET_SHM_CACHED = 0x11000026, 98 | 99 | ISSWAPI_ENABLE_L2CC_MUTEX = 0x20000000, 100 | ISSWAPI_DISABLE_L2CC_MUTEX = 0x20000001, 101 | ISSWAPI_GET_L2CC_MUTEX = 0x20000002, 102 | ISSWAPI_SET_L2CC_MUTEX = 0x20000003, 103 | 104 | ISSWAPI_LOAD_TEE = 0x20000004, 105 | 106 | }; 107 | 108 | /* 109 | * tee_msg_send - generic part of the msg sent to the TEE 110 | */ 111 | struct tee_msg_send { 112 | unsigned int service; 113 | }; 114 | 115 | /* 116 | * tee_msg_recv - default strcutre of TEE service output message 117 | */ 118 | struct tee_msg_recv { 119 | int duration; 120 | uint32_t res; 121 | uint32_t origin; 122 | }; 123 | 124 | /* 125 | * tee_register_irqfwd_xxx - (un)register callback for interrupt forwarding 126 | */ 127 | struct tee_register_irqfwd_send { 128 | struct tee_msg_send header; 129 | struct { 130 | unsigned long cb; 131 | } data; 132 | }; 133 | struct tee_register_irqfwd_recv { 134 | struct tee_msg_recv header; 135 | }; 136 | 137 | /* 138 | * tee_get_l2cc_mutex - input/output argument structures 139 | */ 140 | struct tee_get_l2cc_mutex_send { 141 | struct tee_msg_send header; 142 | }; 143 | struct tee_get_l2cc_mutex_recv { 144 | struct tee_msg_recv header; 145 | struct { 146 | unsigned long paddr; 147 | } data; 148 | }; 149 | 150 | /** 151 | * struct tee_identity - Represents the identity of the client 152 | * @login: Login id 153 | * @uuid: UUID as defined above 154 | */ 155 | struct tee_identity { 156 | uint32_t login; 157 | TEEC_UUID uuid; 158 | }; 159 | 160 | /* 161 | * tee_open_session_data - input arg structure for TEE open session service 162 | */ 163 | struct tee_open_session_data { 164 | struct ta_signed_header_t *ta; 165 | TEEC_UUID uuid; 166 | uint32_t param_types; 167 | TEEC_Value params[TEEC_CONFIG_PAYLOAD_REF_COUNT]; 168 | struct tee_identity client_id; 169 | uint32_t params_flags[TEEC_CONFIG_PAYLOAD_REF_COUNT]; 170 | }; 171 | 172 | /* 173 | * tee_open_session_send - input arg msg for TEE open session service 174 | */ 175 | struct tee_open_session_send { 176 | struct tee_msg_send header; 177 | struct tee_open_session_data data; 178 | }; 179 | 180 | /* 181 | * tee_open_session_recv - output arg structure for TEE open session service 182 | */ 183 | struct tee_open_session_recv { 184 | struct tee_msg_recv header; 185 | uint32_t sess; 186 | TEEC_Value params[TEEC_CONFIG_PAYLOAD_REF_COUNT]; 187 | }; 188 | 189 | /* 190 | * tee_invoke_command_data - input arg structure for TEE invoke cmd service 191 | */ 192 | struct tee_invoke_command_data { 193 | uint32_t sess; 194 | uint32_t cmd; 195 | uint32_t param_types; 196 | TEEC_Value params[TEEC_CONFIG_PAYLOAD_REF_COUNT]; 197 | uint32_t params_flags[TEEC_CONFIG_PAYLOAD_REF_COUNT]; 198 | }; 199 | 200 | struct tee_invoke_command_send { 201 | struct tee_msg_send header; 202 | struct tee_invoke_command_data data; 203 | }; 204 | 205 | /* 206 | * tee_invoke_command_recv - output arg structure for TEE invoke cmd service 207 | */ 208 | struct tee_invoke_command_recv { 209 | struct tee_msg_recv header; 210 | TEEC_Value params[TEEC_CONFIG_PAYLOAD_REF_COUNT]; 211 | }; 212 | 213 | /* 214 | * tee_cancel_command_data - input arg structure for TEE cancel service 215 | */ 216 | struct tee_cancel_command_data { 217 | uint32_t sess; 218 | }; 219 | 220 | /* 221 | * tee_cancel_command_send - input msg structure for TEE cancel service 222 | */ 223 | struct tee_cancel_command_send { 224 | struct tee_msg_send header; 225 | struct tee_cancel_command_data data; 226 | }; 227 | 228 | /* 229 | * tee_close_session_data - input arg structure for TEE close session service 230 | */ 231 | struct tee_close_session_data { 232 | uint32_t sess; 233 | }; 234 | 235 | /* 236 | * tee_close_session_send - input arg msg for TEE close session service 237 | */ 238 | struct tee_close_session_send { 239 | struct tee_msg_send header; 240 | struct tee_close_session_data data; 241 | }; 242 | 243 | /* 244 | * tee_register_rpc_send_data - input arg structure for TEE register rpc service 245 | */ 246 | struct tee_register_rpc_send_data { 247 | uint32_t fnk; 248 | uint32_t bf; 249 | uint32_t nbr_bf; 250 | }; 251 | 252 | /* 253 | * tee_register_rpc_send - input msg structure for TEE register rpc service 254 | */ 255 | struct tee_register_rpc_send { 256 | struct tee_msg_send header; 257 | struct tee_register_rpc_send_data data; 258 | }; 259 | 260 | /* 261 | * tee_core_status_out - output arg structure for TEE status service 262 | */ 263 | #define TEEC_STATUS_MSG_SIZE 80 264 | 265 | struct tee_core_status_out { 266 | struct tee_msg_recv header; 267 | char raw[TEEC_STATUS_MSG_SIZE]; 268 | }; 269 | 270 | #endif /* __TEE_ARMV7_OP_H__ */ 271 | -------------------------------------------------------------------------------- /armtz/tee_tz_priv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #ifndef __TEE_TZ_PRIV__ 14 | #define __TEE_TZ_PRIV__ 15 | 16 | struct tee; 17 | struct shm_pool; 18 | struct tee_rpc_bf; 19 | 20 | struct smc_param { 21 | uint32_t a0; 22 | uint32_t a1; 23 | uint32_t a2; 24 | uint32_t a3; 25 | uint32_t a4; 26 | uint32_t a5; 27 | uint32_t a6; 28 | uint32_t a7; 29 | }; 30 | 31 | struct tee_tz { 32 | uint32_t sess_id; 33 | bool started; 34 | struct tee *tee; 35 | unsigned long shm_paddr; 36 | void *shm_vaddr; 37 | struct shm_pool *shm_pool; 38 | struct mutex mutex; 39 | struct completion c; 40 | int c_waiters; 41 | void *tz_outer_cache_mutex; 42 | struct tee_rpc_bf *rpc_buffers; 43 | bool shm_cached; 44 | struct tee_mutex_wait_private mutex_wait; 45 | struct tee_wait_queue_private wait_queue; 46 | }; 47 | 48 | int tee_smc_call(struct smc_param *param); 49 | 50 | #endif /* __TEE_TZ_PRIV__ */ 51 | -------------------------------------------------------------------------------- /core/Makefile: -------------------------------------------------------------------------------- 1 | CFG_TEE_CORE_CORE_TARGET := armv7 2 | 3 | ######################################################################### 4 | # Set Internal Variables # 5 | # May be modified to match your setup # 6 | ######################################################################### 7 | CFG_TEE_DRV_DEBUGFS?=0 8 | CFG_TEE_CORE_LOG_LEVEL?=2 9 | CFG_TEE_TA_LOG_LEVEL?=2 10 | 11 | ccflags-y+=-O0 12 | ccflags-y+=-Werror 13 | ccflags-y+=-I$(M)/include/linux 14 | ccflags-y+=-I$(M)/include 15 | 16 | ccflags-y+=-DCFG_TEE_DRV_DEBUGFS=${CFG_TEE_DRV_DEBUGFS} 17 | ccflags-y+=-DCFG_TEE_CORE_LOG_LEVEL=${CFG_TEE_CORE_LOG_LEVEL} 18 | ccflags-y+=-DCFG_TEE_TA_LOG_LEVEL=${CFG_TEE_TA_LOG_LEVEL} 19 | 20 | obj-m += optee.o 21 | 22 | optee-objs:= \ 23 | tee_core.o \ 24 | tee_context.o \ 25 | tee_session.o \ 26 | tee_shm.o \ 27 | tee_supp_com.o \ 28 | tee_sysfs.o \ 29 | tee_debugfs.o \ 30 | tee_kernel_api.o \ 31 | tee_mutex_wait.o \ 32 | tee_wait_queue.o \ 33 | 34 | 35 | -------------------------------------------------------------------------------- /core/tee_context.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "tee_shm.h" 22 | #include "tee_core_priv.h" 23 | 24 | 25 | /** 26 | * tee_context_dump - Dump in a buffer the informations (ctx, sess & shm) 27 | * associated to a tee. 28 | */ 29 | int tee_context_dump(struct tee *tee, char *buff, size_t len) 30 | { 31 | struct list_head *ptr_ctx, *ptr_sess, *ptr_shm; 32 | struct tee_context *ctx; 33 | struct tee_session *sess; 34 | struct tee_shm *shm; 35 | int i = 0; 36 | int j = 0; 37 | 38 | int pos = 0; 39 | 40 | BUG_ON(!tee); 41 | 42 | if (len < 80 || list_empty(&tee->list_ctx)) 43 | return 0; 44 | 45 | mutex_lock(&tee->lock); 46 | 47 | list_for_each(ptr_ctx, &tee->list_ctx) { 48 | ctx = list_entry(ptr_ctx, struct tee_context, entry); 49 | 50 | pos += sprintf(buff + pos, 51 | "[%02d] ctx=%p (refcount=%d) (usr=%d)", 52 | i, ctx, 53 | (int)atomic_read(&ctx->refcount. 54 | refcount), 55 | ctx->usr_client); 56 | pos += sprintf(buff + pos, "name=\"%s\" (tgid=%d)\n", 57 | ctx->name, 58 | ctx->tgid); 59 | if ((len - pos) < 80) { 60 | pos = 0; 61 | goto out; 62 | } 63 | 64 | if (list_empty(&ctx->list_sess)) 65 | goto out; 66 | 67 | j = 0; 68 | list_for_each(ptr_sess, &ctx->list_sess) { 69 | sess = list_entry(ptr_sess, 70 | struct tee_session, 71 | entry); 72 | 73 | pos += sprintf(buff + pos, 74 | "[%02d.%d] sess=%p sessid=%08x\n", 75 | i, j, sess, 76 | sess->sessid); 77 | 78 | if ((len - pos) < 80) { 79 | pos = 0; 80 | goto out; 81 | } 82 | 83 | j++; 84 | } 85 | 86 | if (list_empty(&ctx->list_shm)) 87 | goto out; 88 | 89 | j = 0; 90 | list_for_each(ptr_shm, &ctx->list_shm) { 91 | shm = list_entry(ptr_shm, struct tee_shm, entry); 92 | 93 | pos += sprintf(buff + pos, 94 | "[%02d.%d] shm=%p paddr=%p kaddr=%p", 95 | i, j, shm, 96 | &shm->paddr, 97 | shm->kaddr); 98 | pos += sprintf(buff + pos, 99 | " s=%zu(%zu)\n", 100 | shm->size_req, 101 | shm->size_alloc); 102 | if ((len - pos) < 80) { 103 | pos = 0; 104 | goto out; 105 | } 106 | 107 | j++; 108 | } 109 | 110 | i++; 111 | } 112 | 113 | out: 114 | mutex_unlock(&tee->lock); 115 | return pos; 116 | } 117 | 118 | /** 119 | * tee_context_create - Allocate and create a new context. 120 | * Reference on the back-end is requested. 121 | */ 122 | struct tee_context *tee_context_create(struct tee *tee) 123 | { 124 | int ret; 125 | struct tee_context *ctx; 126 | 127 | dev_dbg(_DEV(tee), "%s: >\n", __func__); 128 | 129 | ctx = devm_kzalloc(_DEV(tee), sizeof(struct tee_context), GFP_KERNEL); 130 | if (!ctx) { 131 | dev_err(_DEV(tee), "%s: tee_context allocation failed\n", 132 | __func__); 133 | return ERR_PTR(-ENOMEM); 134 | } 135 | 136 | kref_init(&ctx->refcount); 137 | INIT_LIST_HEAD(&ctx->list_sess); 138 | INIT_LIST_HEAD(&ctx->list_shm); 139 | 140 | ctx->tee = tee; 141 | snprintf(ctx->name, sizeof(ctx->name), "%s", current->comm); 142 | ctx->tgid = current->tgid; 143 | 144 | ret = tee_get(tee); 145 | if (ret) { 146 | devm_kfree(_DEV(tee), ctx); 147 | return ERR_PTR(ret); 148 | } 149 | 150 | mutex_lock(&tee->lock); 151 | tee_inc_stats(&tee->stats[TEE_STATS_CONTEXT_IDX]); 152 | list_add_tail(&ctx->entry, &tee->list_ctx); 153 | mutex_unlock(&tee->lock); 154 | 155 | dev_dbg(_DEV(ctx->tee), "%s: < ctx=%p is created\n", __func__, ctx); 156 | return ctx; 157 | } 158 | 159 | /** 160 | * _tee_context_do_release - Final function to release 161 | * and free a context. 162 | */ 163 | static void _tee_context_do_release(struct kref *kref) 164 | { 165 | struct tee_context *ctx; 166 | struct tee *tee; 167 | 168 | ctx = container_of(kref, struct tee_context, refcount); 169 | 170 | BUG_ON(!ctx || !ctx->tee); 171 | 172 | tee = ctx->tee; 173 | 174 | dev_dbg(_DEV(tee), "%s: > ctx=%p\n", __func__, ctx); 175 | 176 | tee_dec_stats(&tee->stats[TEE_STATS_CONTEXT_IDX]); 177 | list_del(&ctx->entry); 178 | 179 | devm_kfree(_DEV(tee), ctx); 180 | tee_put(tee); 181 | 182 | dev_dbg(_DEV(tee), "%s: < ctx=%p is destroyed\n", __func__, ctx); 183 | } 184 | 185 | /** 186 | * tee_context_get - Increase the reference count of 187 | * the context. 188 | */ 189 | void tee_context_get(struct tee_context *ctx) 190 | { 191 | BUG_ON(!ctx || !ctx->tee); 192 | 193 | kref_get(&ctx->refcount); 194 | 195 | dev_dbg(_DEV(ctx->tee), "%s: ctx=%p, kref=%d\n", __func__, 196 | ctx, (int)atomic_read(&ctx->refcount.refcount)); 197 | } 198 | 199 | static int is_in_list(struct tee *tee, struct list_head *entry) 200 | { 201 | int present = 1; 202 | 203 | if ((entry->next == LIST_POISON1) && (entry->prev == LIST_POISON2)) 204 | present = 0; 205 | return present; 206 | } 207 | 208 | /** 209 | * tee_context_put - Decreases the reference count of 210 | * the context. If 0, the final 211 | * release function is called. 212 | */ 213 | void tee_context_put(struct tee_context *ctx) 214 | { 215 | struct tee_context *_ctx = ctx; 216 | struct tee *tee; 217 | 218 | BUG_ON(!ctx || !ctx->tee); 219 | tee = ctx->tee; 220 | 221 | if (!is_in_list(tee, &ctx->entry)) 222 | return; 223 | 224 | kref_put(&ctx->refcount, _tee_context_do_release); 225 | 226 | dev_dbg(_DEV(tee), "%s: ctx=%p, kref=%d\n", __func__, 227 | _ctx, (int)atomic_read(&ctx->refcount.refcount)); 228 | } 229 | 230 | /** 231 | * tee_context_destroy - Request to destroy a context. 232 | */ 233 | void tee_context_destroy(struct tee_context *ctx) 234 | { 235 | struct tee *tee; 236 | 237 | if (!ctx || !ctx->tee) 238 | return; 239 | 240 | tee = ctx->tee; 241 | 242 | dev_dbg(_DEV(tee), "%s: ctx=%p\n", __func__, ctx); 243 | 244 | mutex_lock(&tee->lock); 245 | tee_context_put(ctx); 246 | mutex_unlock(&tee->lock); 247 | } 248 | 249 | int tee_context_copy_from_client(const struct tee_context *ctx, 250 | void *dest, const void *src, size_t size) 251 | { 252 | int res = 0; 253 | 254 | if (dest && src && (size > 0)) { 255 | if (ctx->usr_client) 256 | res = copy_from_user(dest, src, size); 257 | else 258 | memcpy(dest, src, size); 259 | } 260 | return res; 261 | } 262 | 263 | struct tee_shm *tee_context_alloc_shm_tmp(struct tee_context *ctx, 264 | size_t size, const void *src, 265 | int type) 266 | { 267 | struct tee_shm *shm; 268 | 269 | type &= (TEEC_MEM_INPUT | TEEC_MEM_OUTPUT); 270 | 271 | shm = tee_shm_alloc(ctx->tee, size, 272 | TEE_SHM_MAPPED | TEE_SHM_TEMP | type); 273 | if (IS_ERR_OR_NULL(shm)) { 274 | dev_err(_DEV(ctx->tee), "%s: buffer allocation failed (%ld)\n", 275 | __func__, PTR_ERR(shm)); 276 | return shm; 277 | } 278 | 279 | shm->ctx = ctx; 280 | 281 | if (type & TEEC_MEM_INPUT) { 282 | if (tee_context_copy_from_client(ctx, shm->kaddr, src, size)) { 283 | dev_err(_DEV(ctx->tee), 284 | "%s: tee_context_copy_from_client failed\n", 285 | __func__); 286 | tee_shm_free(shm); 287 | shm = NULL; 288 | } 289 | } 290 | return shm; 291 | } 292 | 293 | struct tee_shm *tee_context_create_tmpref_buffer(struct tee_context *ctx, 294 | size_t size, 295 | const void *buffer, int type) 296 | { 297 | struct tee_shm *shm = NULL; 298 | int flags; 299 | 300 | switch (type) { 301 | case TEEC_MEMREF_TEMP_OUTPUT: 302 | flags = TEEC_MEM_OUTPUT; 303 | break; 304 | case TEEC_MEMREF_TEMP_INPUT: 305 | flags = TEEC_MEM_INPUT; 306 | break; 307 | case TEEC_MEMREF_TEMP_INOUT: 308 | flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; 309 | break; 310 | default: 311 | BUG_ON(1); 312 | }; 313 | shm = tee_context_alloc_shm_tmp(ctx, size, buffer, flags); 314 | return shm; 315 | } 316 | -------------------------------------------------------------------------------- /core/tee_core.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | /* #define DEBUG */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "linux/tee_core.h" 31 | #include "linux/tee_ioc.h" 32 | 33 | #include "tee_core_priv.h" 34 | 35 | #include "tee_sysfs.h" 36 | #include "tee_debugfs.h" 37 | #include "tee_shm.h" 38 | #include "tee_supp_com.h" 39 | 40 | #define _TEE_CORE_FW_VER "1:0.1" 41 | 42 | static char *_tee_supp_app_name = "tee-supplicant"; 43 | 44 | /* Store the class misc reference */ 45 | static struct class *misc_class; 46 | 47 | static int device_match(struct device *device, const void *devname) 48 | { 49 | struct tee *tee = dev_get_drvdata(device); 50 | int ret = strncmp(devname, tee->name, sizeof(tee->name)); 51 | 52 | BUG_ON(!tee); 53 | if (ret == 0) 54 | return 1; 55 | else 56 | return 0; 57 | } 58 | 59 | /* 60 | * For the kernel api. 61 | * Get a reference on a device tee from the device needed 62 | */ 63 | struct tee *tee_get_tee(const char *devname) 64 | { 65 | struct device *device; 66 | 67 | if (!devname) 68 | return NULL; 69 | device = class_find_device(misc_class, NULL, devname, device_match); 70 | if (!device) { 71 | pr_err("%s:%d - can't find device [%s]\n", __func__, __LINE__, 72 | devname); 73 | return NULL; 74 | } 75 | 76 | return dev_get_drvdata(device); 77 | } 78 | 79 | void tee_inc_stats(struct tee_stats_entry *entry) 80 | { 81 | entry->count++; 82 | if (entry->count > entry->max) 83 | entry->max = entry->count; 84 | } 85 | 86 | void tee_dec_stats(struct tee_stats_entry *entry) 87 | { 88 | entry->count--; 89 | } 90 | 91 | /** 92 | * tee_get - increases refcount of the tee 93 | * @tee: [in] tee to increase refcount of 94 | * 95 | * @note: If tee.ops.start() callback function is available, 96 | * it is called when refcount is equal at 1. 97 | */ 98 | int tee_get(struct tee *tee) 99 | { 100 | int ret = 0; 101 | 102 | BUG_ON(!tee); 103 | 104 | if (atomic_inc_return(&tee->refcount) == 1) { 105 | BUG_ON(!try_module_get(tee->ops->owner)); 106 | dev_dbg(_DEV(tee), "%s: refcount=1 call %s::start()...\n", 107 | __func__, tee->name); 108 | get_device(tee->dev); 109 | if (tee->ops->start) 110 | ret = tee->ops->start(tee); 111 | } 112 | if (ret) { 113 | put_device(tee->dev); 114 | module_put(tee->ops->owner); 115 | dev_err(_DEV(tee), "%s: %s::start() failed, err=%d\n", 116 | __func__, tee->name, ret); 117 | atomic_dec(&tee->refcount); 118 | } else { 119 | int count = (int)atomic_read(&tee->refcount); 120 | 121 | dev_dbg(_DEV(tee), "%s: refcount=%d\n", __func__, count); 122 | if (count > tee->max_refcount) 123 | tee->max_refcount = count; 124 | } 125 | return ret; 126 | } 127 | 128 | /** 129 | * tee_put - decreases refcount of the tee 130 | * @tee: [in] tee to reduce refcount of 131 | * 132 | * @note: If tee.ops.stop() callback function is available, 133 | * it is called when refcount is equal at 0. 134 | */ 135 | int tee_put(struct tee *tee) 136 | { 137 | int ret = 0; 138 | int count; 139 | 140 | BUG_ON(!tee); 141 | 142 | if (atomic_dec_and_test(&tee->refcount)) { 143 | dev_dbg(_DEV(tee), "%s: refcount=0 call %s::stop()...\n", 144 | __func__, tee->name); 145 | if (tee->ops->stop) 146 | ret = tee->ops->stop(tee); 147 | module_put(tee->ops->owner); 148 | put_device(tee->dev); 149 | } 150 | if (ret) { 151 | dev_err(_DEV(tee), "%s: %s::stop() has failed, ret=%d\n", 152 | __func__, tee->name, ret); 153 | } 154 | 155 | count = (int)atomic_read(&tee->refcount); 156 | dev_dbg(_DEV(tee), "%s: refcount=%d\n", __func__, count); 157 | return ret; 158 | } 159 | 160 | static int tee_supp_open(struct tee *tee) 161 | { 162 | int ret = 0; 163 | 164 | dev_dbg(_DEV(tee), "%s: appclient=\"%s\" pid=%d\n", __func__, 165 | current->comm, current->pid); 166 | 167 | BUG_ON(!tee->rpc); 168 | 169 | if (strncmp(_tee_supp_app_name, current->comm, 170 | strlen(_tee_supp_app_name)) == 0) { 171 | if (atomic_add_return(1, &tee->rpc->used) > 1) { 172 | ret = -EBUSY; 173 | dev_err(tee->dev, "%s: ERROR Only one Supplicant is allowed\n", 174 | __func__); 175 | atomic_sub(1, &tee->rpc->used); 176 | } 177 | } 178 | 179 | return ret; 180 | } 181 | 182 | static void tee_supp_release(struct tee *tee) 183 | { 184 | dev_dbg(_DEV(tee), "%s: appclient=\"%s\" pid=%d\n", __func__, 185 | current->comm, current->pid); 186 | 187 | BUG_ON(!tee->rpc); 188 | 189 | if ((atomic_read(&tee->rpc->used) == 1) && 190 | (strncmp(_tee_supp_app_name, current->comm, 191 | strlen(_tee_supp_app_name)) == 0)) 192 | atomic_sub(1, &tee->rpc->used); 193 | } 194 | 195 | static int tee_ctx_open(struct inode *inode, struct file *filp) 196 | { 197 | struct tee_context *ctx; 198 | struct tee *tee; 199 | int ret; 200 | 201 | tee = container_of(filp->private_data, struct tee, miscdev); 202 | 203 | BUG_ON(!tee); 204 | BUG_ON(tee->miscdev.minor != iminor(inode)); 205 | 206 | dev_dbg(_DEV(tee), "%s: > name=\"%s\"\n", __func__, tee->name); 207 | 208 | ret = tee_supp_open(tee); 209 | if (ret) 210 | return ret; 211 | 212 | ctx = tee_context_create(tee); 213 | if (IS_ERR_OR_NULL(ctx)) 214 | return PTR_ERR(ctx); 215 | 216 | ctx->usr_client = 1; 217 | filp->private_data = ctx; 218 | 219 | dev_dbg(_DEV(tee), "%s: < ctx=%p is created\n", __func__, (void *)ctx); 220 | 221 | return 0; 222 | } 223 | 224 | static int tee_ctx_release(struct inode *inode, struct file *filp) 225 | { 226 | struct tee_context *ctx = filp->private_data; 227 | struct tee *tee; 228 | 229 | if (!ctx) 230 | return -EINVAL; 231 | 232 | BUG_ON(!ctx->tee); 233 | tee = ctx->tee; 234 | BUG_ON(tee->miscdev.minor != iminor(inode)); 235 | 236 | dev_dbg(_DEV(tee), "%s: > ctx=%p\n", __func__, ctx); 237 | 238 | tee_context_destroy(ctx); 239 | tee_supp_release(tee); 240 | 241 | dev_dbg(_DEV(tee), "%s: < ctx=%p is destroyed\n", __func__, ctx); 242 | return 0; 243 | } 244 | 245 | static int tee_do_create_session(struct tee_context *ctx, 246 | struct tee_cmd_io __user *u_cmd) 247 | { 248 | int ret = -EINVAL; 249 | struct tee_cmd_io k_cmd; 250 | struct tee *tee; 251 | 252 | tee = ctx->tee; 253 | BUG_ON(!ctx->usr_client); 254 | 255 | dev_dbg(_DEV(tee), "%s: >\n", __func__); 256 | 257 | if (copy_from_user(&k_cmd, (void *)u_cmd, sizeof(struct tee_cmd_io))) { 258 | dev_err(_DEV(tee), "%s: copy_from_user failed\n", __func__); 259 | goto exit; 260 | } 261 | 262 | if (k_cmd.fd_sess > 0) { 263 | dev_err(_DEV(tee), "%s: invalid fd_sess %d\n", __func__, 264 | k_cmd.fd_sess); 265 | goto exit; 266 | } 267 | 268 | if ((k_cmd.op == NULL) || (k_cmd.uuid == NULL) || 269 | ((k_cmd.data != NULL) && (k_cmd.data_size == 0)) || 270 | ((k_cmd.data == NULL) && (k_cmd.data_size != 0))) { 271 | dev_err(_DEV(tee), 272 | "%s: op or/and data parameters are not valid\n", 273 | __func__); 274 | goto exit; 275 | } 276 | 277 | ret = tee_session_create_fd(ctx, &k_cmd); 278 | put_user(k_cmd.err, &u_cmd->err); 279 | put_user(k_cmd.origin, &u_cmd->origin); 280 | if (ret) 281 | goto exit; 282 | 283 | put_user(k_cmd.fd_sess, &u_cmd->fd_sess); 284 | 285 | exit: 286 | dev_dbg(_DEV(tee), "%s: < ret=%d, sessfd=%d\n", __func__, ret, 287 | k_cmd.fd_sess); 288 | return ret; 289 | } 290 | 291 | static int tee_do_shm_alloc(struct tee_context *ctx, 292 | struct tee_shm_io __user *u_shm) 293 | { 294 | int ret = -EINVAL; 295 | struct tee_shm_io k_shm; 296 | struct tee *tee = ctx->tee; 297 | 298 | BUG_ON(!ctx->usr_client); 299 | 300 | dev_dbg(_DEV(tee), "%s: >\n", __func__); 301 | 302 | if (copy_from_user(&k_shm, (void *)u_shm, sizeof(struct tee_shm_io))) { 303 | dev_err(_DEV(tee), "%s: copy_from_user failed\n", __func__); 304 | goto exit; 305 | } 306 | 307 | if ((k_shm.buffer != NULL) || (k_shm.fd_shm != 0) || 308 | /*(k_shm.flags & ~(tee->shm_flags)) ||*/ 309 | ((k_shm.flags & tee->shm_flags) == 0) || (k_shm.registered != 0)) { 310 | dev_err(_DEV(tee), 311 | "%s: shm parameters are not valid %p %d %08x %08x %d\n", 312 | __func__, (void *)k_shm.buffer, k_shm.fd_shm, 313 | (unsigned int)k_shm.flags, (unsigned int)tee->shm_flags, 314 | k_shm.registered); 315 | goto exit; 316 | } 317 | 318 | ret = tee_shm_alloc_io(ctx, &k_shm); 319 | if (ret) 320 | goto exit; 321 | 322 | put_user(k_shm.fd_shm, &u_shm->fd_shm); 323 | put_user(k_shm.flags, &u_shm->flags); 324 | 325 | exit: 326 | dev_dbg(_DEV(tee), "%s: < ret=%d, shmfd=%d\n", __func__, ret, 327 | k_shm.fd_shm); 328 | return ret; 329 | } 330 | 331 | static int tee_do_get_fd_for_rpc_shm(struct tee_context *ctx, 332 | struct tee_shm_io __user *u_shm) 333 | { 334 | int ret = -EINVAL; 335 | struct tee_shm_io k_shm; 336 | struct tee *tee = ctx->tee; 337 | 338 | dev_dbg(_DEV(tee), "%s: >\n", __func__); 339 | BUG_ON(!ctx->usr_client); 340 | 341 | if (copy_from_user(&k_shm, (void *)u_shm, sizeof(struct tee_shm_io))) { 342 | dev_err(_DEV(tee), "%s: copy_from_user failed\n", __func__); 343 | goto exit; 344 | } 345 | 346 | if ((k_shm.buffer == NULL) || (k_shm.size == 0) || (k_shm.fd_shm != 0) 347 | || (k_shm.flags & ~(tee->shm_flags)) 348 | || ((k_shm.flags & tee->shm_flags) == 0) 349 | || (k_shm.registered != 0)) { 350 | dev_err(_DEV(tee), "%s: shm parameters are not valid\n", 351 | __func__); 352 | goto exit; 353 | } 354 | 355 | ret = tee_shm_fd_for_rpc(ctx, &k_shm); 356 | if (ret) 357 | goto exit; 358 | 359 | put_user(k_shm.fd_shm, &u_shm->fd_shm); 360 | 361 | exit: 362 | dev_dbg(_DEV(tee), "%s: < ret=%d, shmfd=%d\n", __func__, ret, 363 | k_shm.fd_shm); 364 | return ret; 365 | } 366 | 367 | static long tee_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 368 | { 369 | int ret = -EINVAL; 370 | struct tee_context *ctx = filp->private_data; 371 | void __user *u_arg; 372 | 373 | BUG_ON(!ctx); 374 | BUG_ON(!ctx->tee); 375 | 376 | dev_dbg(_DEV(ctx->tee), "%s: > cmd nr=%d\n", __func__, _IOC_NR(cmd)); 377 | 378 | #ifdef CONFIG_COMPAT 379 | if (is_compat_task()) 380 | u_arg = compat_ptr(arg); 381 | else 382 | u_arg = (void __user *)arg; 383 | #else 384 | u_arg = (void __user *)arg; 385 | #endif 386 | 387 | switch (cmd) { 388 | case TEE_OPEN_SESSION_IOC: 389 | ret = tee_do_create_session(ctx, 390 | (struct tee_cmd_io __user *)u_arg); 391 | break; 392 | case TEE_ALLOC_SHM_IOC: 393 | ret = tee_do_shm_alloc(ctx, (struct tee_shm_io __user *)u_arg); 394 | break; 395 | case TEE_GET_FD_FOR_RPC_SHM_IOC: 396 | ret = tee_do_get_fd_for_rpc_shm(ctx, 397 | (struct tee_shm_io __user *)u_arg); 398 | break; 399 | default: 400 | ret = -ENOSYS; 401 | break; 402 | } 403 | 404 | dev_dbg(_DEV(ctx->tee), "%s: < ret=%d\n", __func__, ret); 405 | 406 | return ret; 407 | } 408 | 409 | static const struct file_operations tee_fops = { 410 | .owner = THIS_MODULE, 411 | .read = tee_supp_read, 412 | .write = tee_supp_write, 413 | .open = tee_ctx_open, 414 | .release = tee_ctx_release, 415 | #ifdef CONFIG_COMPAT 416 | .compat_ioctl = tee_ioctl, 417 | #endif 418 | .unlocked_ioctl = tee_ioctl 419 | }; 420 | 421 | static void tee_plt_device_release(struct device *dev) 422 | { 423 | pr_debug("%s: (dev=%p)....\n", __func__, dev); 424 | } 425 | 426 | struct tee *tee_core_alloc(struct device *dev, char *name, int id, 427 | const struct tee_ops *ops, size_t len) 428 | { 429 | struct tee *tee; 430 | 431 | if (!dev || !name || !ops || 432 | !ops->open || !ops->close || !ops->alloc || !ops->free) 433 | return NULL; 434 | 435 | tee = devm_kzalloc(dev, sizeof(struct tee) + len, GFP_KERNEL); 436 | if (!tee) { 437 | dev_err(dev, "%s: kzalloc failed\n", __func__); 438 | return NULL; 439 | } 440 | 441 | if (!dev->release) 442 | dev->release = tee_plt_device_release; 443 | 444 | tee->dev = dev; 445 | tee->id = id; 446 | tee->ops = ops; 447 | tee->priv = &tee[1]; 448 | 449 | snprintf(tee->name, sizeof(tee->name), "optee%s%02d", name, tee->id); 450 | pr_info("TEE core: Alloc the misc device \"%s\" (id=%d)\n", tee->name, 451 | tee->id); 452 | 453 | tee->miscdev.parent = dev; 454 | tee->miscdev.minor = MISC_DYNAMIC_MINOR; 455 | tee->miscdev.name = tee->name; 456 | tee->miscdev.fops = &tee_fops; 457 | 458 | mutex_init(&tee->lock); 459 | atomic_set(&tee->refcount, 0); 460 | INIT_LIST_HEAD(&tee->list_ctx); 461 | INIT_LIST_HEAD(&tee->list_rpc_shm); 462 | 463 | tee->state = TEE_OFFLINE; 464 | tee->shm_flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; 465 | tee->test = 0; 466 | 467 | tee_supp_init(tee); 468 | 469 | return tee; 470 | } 471 | EXPORT_SYMBOL(tee_core_alloc); 472 | 473 | int tee_core_free(struct tee *tee) 474 | { 475 | if (tee) { 476 | tee_supp_deinit(tee); 477 | devm_kfree(tee->dev, tee); 478 | } 479 | return 0; 480 | } 481 | EXPORT_SYMBOL(tee_core_free); 482 | 483 | int tee_core_add(struct tee *tee) 484 | { 485 | int rc = 0; 486 | 487 | if (!tee) 488 | return -EINVAL; 489 | 490 | rc = misc_register(&tee->miscdev); 491 | if (rc != 0) { 492 | pr_err("TEE Core: misc_register() failed name=\"%s\"\n", 493 | tee->name); 494 | return rc; 495 | } 496 | 497 | dev_set_drvdata(tee->miscdev.this_device, tee); 498 | 499 | tee_init_sysfs(tee); 500 | tee_create_debug_dir(tee); 501 | 502 | /* Register a static reference on the class misc 503 | * to allow finding device by class */ 504 | BUG_ON(!tee->miscdev.this_device->class); 505 | if (misc_class) 506 | BUG_ON(misc_class != tee->miscdev.this_device->class); 507 | else 508 | misc_class = tee->miscdev.this_device->class; 509 | 510 | pr_info("TEE Core: Register the misc device \"%s\" (id=%d,minor=%d)\n", 511 | dev_name(tee->miscdev.this_device), tee->id, 512 | tee->miscdev.minor); 513 | return rc; 514 | } 515 | EXPORT_SYMBOL(tee_core_add); 516 | 517 | int tee_core_del(struct tee *tee) 518 | { 519 | if (tee) { 520 | pr_info("TEE Core: Destroy the misc device \"%s\" (id=%d)\n", 521 | dev_name(tee->miscdev.this_device), tee->id); 522 | 523 | tee_cleanup_sysfs(tee); 524 | tee_delete_debug_dir(tee); 525 | 526 | if (tee->miscdev.minor != MISC_DYNAMIC_MINOR) { 527 | pr_info("TEE Core: Deregister the misc device \"%s\" (id=%d)\n", 528 | dev_name(tee->miscdev.this_device), tee->id); 529 | misc_deregister(&tee->miscdev); 530 | } 531 | } 532 | 533 | tee_core_free(tee); 534 | 535 | return 0; 536 | } 537 | EXPORT_SYMBOL(tee_core_del); 538 | 539 | static int __init tee_core_init(void) 540 | { 541 | pr_info("\nTEE Core Framework initialization (ver %s)\n", 542 | _TEE_CORE_FW_VER); 543 | tee_init_debugfs(); 544 | 545 | return 0; 546 | } 547 | 548 | static void __exit tee_core_exit(void) 549 | { 550 | tee_exit_debugfs(); 551 | pr_info("TEE Core Framework unregistered\n"); 552 | } 553 | 554 | module_init(tee_core_init); 555 | module_exit(tee_core_exit); 556 | 557 | MODULE_AUTHOR("STMicroelectronics"); 558 | MODULE_DESCRIPTION("STM Secure TEE Framework/Core TEEC v1.0"); 559 | MODULE_SUPPORTED_DEVICE(""); 560 | MODULE_VERSION(_TEE_CORE_FW_VER); 561 | MODULE_LICENSE("GPL"); 562 | -------------------------------------------------------------------------------- /core/tee_core_priv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #ifndef __TEE_CORE_PRIV_H__ 14 | #define __TEE_CORE_PRIV_H__ 15 | 16 | #include "linux/tee_core.h" 17 | #include "linux/tee_ioc.h" 18 | 19 | /* from tee_core_module.c */ 20 | int tee_get(struct tee *tee); 21 | int tee_put(struct tee *tee); 22 | 23 | void tee_inc_stats(struct tee_stats_entry *entry); 24 | void tee_dec_stats(struct tee_stats_entry *entry); 25 | 26 | /* from tee_context.c */ 27 | int tee_context_dump(struct tee *tee, char *buff, size_t len); 28 | 29 | struct tee_context *tee_context_create(struct tee *tee); 30 | void tee_context_destroy(struct tee_context *ctx); 31 | 32 | void tee_context_get(struct tee_context *ctx); 33 | void tee_context_put(struct tee_context *ctx); 34 | 35 | struct tee_shm *tee_context_create_tmpref_buffer(struct tee_context *ctx, 36 | size_t size, 37 | const void *buffer, int type); 38 | struct tee_shm *tee_context_alloc_shm_tmp(struct tee_context *ctx, size_t size, 39 | const void *data, int type); 40 | int tee_context_copy_from_client(const struct tee_context *ctx, void *dest, 41 | const void *src, size_t size); 42 | 43 | /* from tee_session.c */ 44 | int tee_session_create_fd(struct tee_context *ctx, struct tee_cmd_io *cmd_io); 45 | struct tee_session *tee_session_create_and_open(struct tee_context *ctx, 46 | struct tee_cmd_io *cmd_io); 47 | int tee_session_close_and_destroy(struct tee_session *sess); 48 | 49 | struct tee *tee_get_tee(const char *devname); 50 | int tee_session_invoke_be(struct tee_session *sess, struct tee_cmd_io *cmd_io); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /core/tee_debugfs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "linux/tee_core.h" 19 | #include "tee_debugfs.h" 20 | 21 | static struct dentry *tee_debugfs_dir; 22 | 23 | static ssize_t tee_trace_read(struct file *filp, char __user *userbuf, 24 | size_t count, loff_t *ppos) 25 | { 26 | struct tee *tee = filp->private_data; 27 | 28 | char buff[258]; 29 | int len = sprintf(buff, "device=%s\n NO LOG AVAILABLE\n", tee->name); 30 | 31 | return simple_read_from_buffer(userbuf, count, ppos, buff, len); 32 | } 33 | 34 | static const struct file_operations log_tee_ops = { 35 | .read = tee_trace_read, 36 | .open = simple_open, 37 | .llseek = generic_file_llseek, 38 | }; 39 | 40 | void tee_create_debug_dir(struct tee *tee) 41 | { 42 | struct dentry *entry; 43 | struct device *dev = tee->miscdev.this_device; 44 | 45 | if (!tee_debugfs_dir) 46 | return; 47 | 48 | tee->dbg_dir = debugfs_create_dir(dev_name(dev), tee_debugfs_dir); 49 | if (!tee->dbg_dir) 50 | goto error_create_file; 51 | 52 | entry = debugfs_create_file("log", S_IRUGO, tee->dbg_dir, 53 | tee, &log_tee_ops); 54 | if (!entry) 55 | goto error_create_file; 56 | 57 | return; 58 | 59 | error_create_file: 60 | dev_err(dev, "can't create debugfs file\n"); 61 | tee_delete_debug_dir(tee); 62 | } 63 | 64 | void tee_delete_debug_dir(struct tee *tee) 65 | { 66 | if (!tee || !tee->dbg_dir) 67 | return; 68 | 69 | debugfs_remove_recursive(tee->dbg_dir); 70 | } 71 | 72 | void __init tee_init_debugfs(void) 73 | { 74 | if (debugfs_initialized()) { 75 | tee_debugfs_dir = debugfs_create_dir("tee", NULL); 76 | if (IS_ERR(tee_debugfs_dir)) 77 | pr_err("can't create debugfs dir\n"); 78 | } 79 | } 80 | 81 | void __exit tee_exit_debugfs(void) 82 | { 83 | if (tee_debugfs_dir) 84 | debugfs_remove(tee_debugfs_dir); 85 | } 86 | -------------------------------------------------------------------------------- /core/tee_debugfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #ifndef __TEE_DEBUGFS_H__ 14 | #define __TEE_DEBUGFS_H__ 15 | 16 | struct tee; 17 | 18 | void tee_create_debug_dir(struct tee *tee); 19 | void tee_delete_debug_dir(struct tee *tee); 20 | 21 | void __init tee_init_debugfs(void); 22 | void __exit tee_exit_debugfs(void); 23 | 24 | #endif /* __TEE_DEBUGFS_H__ */ 25 | -------------------------------------------------------------------------------- /core/tee_kernel_api.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "linux/tee_kernel_api.h" 20 | #include "linux/tee_core.h" 21 | #include "linux/tee_ioc.h" 22 | 23 | #include "tee_core_priv.h" 24 | #include "tee_shm.h" 25 | #include "tee_supp_com.h" 26 | 27 | #define TEE_TZ_DEVICE_NAME "opteearmtz00" 28 | 29 | static void reset_tee_cmd(struct tee_cmd_io *cmd) 30 | { 31 | memset(cmd, 0, sizeof(struct tee_cmd_io)); 32 | cmd->fd_sess = -1; 33 | cmd->cmd = 0; 34 | cmd->uuid = NULL; 35 | cmd->origin = TEEC_ORIGIN_API; 36 | cmd->err = TEEC_SUCCESS; 37 | cmd->data = NULL; 38 | cmd->data_size = 0; 39 | cmd->op = NULL; 40 | } 41 | 42 | TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *context) 43 | { 44 | struct tee *tee; 45 | struct tee_context *ctx; 46 | pr_cont("%s: > name=\"%s\"\n", __func__, name); 47 | 48 | if (!context) 49 | return TEEC_ERROR_BAD_PARAMETERS; 50 | 51 | context->fd = 0; 52 | 53 | if (name == NULL) 54 | strncpy(context->devname, TEE_TZ_DEVICE_NAME, 55 | sizeof(context->devname)); 56 | else 57 | strncpy(context->devname, name, sizeof(context->devname)); 58 | 59 | tee = tee_get_tee(context->devname); 60 | if (!tee) { 61 | pr_err("%s - can't get device [%s]\n", __func__, name); 62 | return TEEC_ERROR_BAD_PARAMETERS; 63 | } 64 | 65 | ctx = tee_context_create(tee); 66 | if (IS_ERR_OR_NULL(ctx)) 67 | return TEEC_ERROR_BAD_PARAMETERS; 68 | 69 | ctx->usr_client = 0; 70 | 71 | /* TODO fixme will not work on 64-bit platform */ 72 | context->fd = (int)(uintptr_t)ctx; 73 | BUG_ON(ctx != (struct tee_context *)(uintptr_t)context->fd); 74 | 75 | pr_cont("%s: < ctx=%p is created\n", __func__, (void *)ctx); 76 | return TEEC_SUCCESS; 77 | } 78 | EXPORT_SYMBOL(TEEC_InitializeContext); 79 | 80 | void TEEC_FinalizeContext(TEEC_Context *context) 81 | { 82 | if (!context || !context->fd) { 83 | pr_err("%s - can't release context %p:[%s]\n", __func__, 84 | context, (context 85 | && context->devname) ? context->devname : ""); 86 | return; 87 | } 88 | /* TODO fixme will not work on 64-bit platform */ 89 | tee_context_destroy((struct tee_context *)(uintptr_t)context->fd); 90 | return; 91 | } 92 | EXPORT_SYMBOL(TEEC_FinalizeContext); 93 | 94 | TEEC_Result TEEC_OpenSession(TEEC_Context *context, 95 | TEEC_Session *session, 96 | const TEEC_UUID *destination, 97 | uint32_t connectionMethod, 98 | const void *connectionData, 99 | TEEC_Operation *operation, 100 | uint32_t *return_origin) 101 | { 102 | TEEC_Operation dummy_op; 103 | struct tee_cmd_io cmd; 104 | struct tee_session *sess; 105 | struct tee_context *ctx; 106 | 107 | if (!operation) { 108 | /* 109 | * The code here exist because Global Platform API states that 110 | * it is allowed to give operation as a NULL pointer. 111 | * In kernel and secure world we in most cases don't want 112 | * this to be NULL, hence we use this dummy operation when 113 | * a client doesn't provide any operation. 114 | */ 115 | memset(&dummy_op, 0, sizeof(TEEC_Operation)); 116 | operation = &dummy_op; 117 | } 118 | 119 | if (!context || !session || !destination || !operation 120 | || !return_origin) 121 | return TEEC_ERROR_BAD_PARAMETERS; 122 | 123 | session->fd = 0; 124 | 125 | /* TODO fixme will not work on 64-bit platform */ 126 | ctx = (struct tee_context *)(uintptr_t)context->fd; 127 | reset_tee_cmd(&cmd); 128 | cmd.op = operation; 129 | cmd.uuid = (TEEC_UUID *) destination; 130 | 131 | sess = tee_session_create_and_open(ctx, &cmd); 132 | if (IS_ERR_OR_NULL(sess)) { 133 | if (cmd.origin) 134 | *return_origin = cmd.origin; 135 | else 136 | *return_origin = TEEC_ORIGIN_COMMS; 137 | if (cmd.err) 138 | return cmd.err; 139 | else 140 | return TEEC_ERROR_COMMUNICATION; 141 | } else { 142 | *return_origin = cmd.origin; 143 | /* TODO fixme will not work on 64-bit platform */ 144 | session->fd = (int)(uintptr_t)sess; 145 | BUG_ON(sess != (struct tee_session *)(uintptr_t)session->fd); 146 | return cmd.err; 147 | } 148 | } 149 | EXPORT_SYMBOL(TEEC_OpenSession); 150 | 151 | void TEEC_CloseSession(TEEC_Session *session) 152 | { 153 | if (session && session->fd) { 154 | /* TODO fixme will not work on 64-bit platform */ 155 | struct tee_session *sess = 156 | (struct tee_session *)(uintptr_t)session->fd; 157 | tee_session_close_and_destroy(sess); 158 | } 159 | } 160 | EXPORT_SYMBOL(TEEC_CloseSession); 161 | 162 | TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, 163 | uint32_t commandID, 164 | TEEC_Operation *operation, 165 | uint32_t *return_origin) 166 | { 167 | int ret = 0; 168 | struct tee_cmd_io cmd; 169 | struct tee_session *sess; 170 | 171 | if (!session || !operation || !return_origin || !session->fd) 172 | return TEEC_ERROR_BAD_PARAMETERS; 173 | 174 | /* TODO fixme will not work on 64-bit platform */ 175 | sess = (struct tee_session *)(uintptr_t)session->fd; 176 | reset_tee_cmd(&cmd); 177 | cmd.cmd = commandID; 178 | cmd.op = operation; 179 | 180 | ret = tee_session_invoke_be(sess, &cmd); 181 | if (ret) { 182 | if (cmd.origin) 183 | *return_origin = cmd.origin; 184 | else 185 | *return_origin = TEEC_ORIGIN_COMMS; 186 | if (cmd.err) 187 | return cmd.err; 188 | else 189 | return TEEC_ERROR_COMMUNICATION; 190 | } else { 191 | *return_origin = cmd.origin; 192 | return cmd.err; 193 | } 194 | } 195 | EXPORT_SYMBOL(TEEC_InvokeCommand); 196 | 197 | TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context, 198 | TEEC_SharedMemory *sharedMem) 199 | { 200 | if (!sharedMem) 201 | return TEEC_ERROR_BAD_PARAMETERS; 202 | 203 | sharedMem->registered = 1; 204 | return TEEC_SUCCESS; 205 | } 206 | EXPORT_SYMBOL(TEEC_RegisterSharedMemory); 207 | 208 | TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context, 209 | TEEC_SharedMemory *shared_memory) 210 | { 211 | struct tee_shm_io shm_io; 212 | int ret; 213 | struct tee_shm *shm; 214 | 215 | if (!context || !context->ctx || !shared_memory) 216 | return TEEC_ERROR_BAD_PARAMETERS; 217 | 218 | shm_io.size = shared_memory->size; 219 | shm_io.flags = shared_memory->flags | TEEC_MEM_KAPI; 220 | ret = tee_shm_alloc_io(context->ctx, &shm_io); 221 | if (ret) { 222 | pr_err("%s: tee_shm_alloc_io(%zd) failed\n", __func__, 223 | shared_memory->size); 224 | return TEEC_ERROR_OUT_OF_MEMORY; 225 | } 226 | 227 | shared_memory->registered = 0; 228 | shared_memory->flags = shm_io.flags; 229 | shared_memory->d.fd = shm_io.fd_shm; 230 | 231 | shm = (struct tee_shm *)(long)shm_io.fd_shm; 232 | shared_memory->buffer = shm->kaddr; 233 | 234 | pr_debug("%s(%d) => fd=%d, kaddr=%p\n", __func__, 235 | shm_io.size, shm_io.fd_shm, (void *)shared_memory->buffer); 236 | 237 | return TEEC_SUCCESS; 238 | } 239 | EXPORT_SYMBOL(TEEC_AllocateSharedMemory); 240 | 241 | void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *shared_memory) 242 | { 243 | struct tee_shm *shm; 244 | 245 | if (!shared_memory || shared_memory->registered) 246 | return; 247 | 248 | pr_debug("%s (vaddr = %p)\n", __func__, shared_memory->buffer); 249 | 250 | shm = (struct tee_shm *)(long)shared_memory->d.fd; 251 | tee_shm_free_io(shm); 252 | 253 | shared_memory->buffer = NULL; 254 | shared_memory->d.fd = 0; 255 | } 256 | EXPORT_SYMBOL(TEEC_ReleaseSharedMemory); 257 | -------------------------------------------------------------------------------- /core/tee_mutex_wait.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Linaro Limited 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #include 14 | #include "tee_mutex_wait.h" 15 | 16 | struct tee_mutex_wait { 17 | struct list_head link; 18 | struct completion comp; 19 | struct mutex mu; 20 | u32 wait_after; 21 | u32 key; 22 | }; 23 | 24 | /* 25 | * Compares two serial numbers using Serial Number Arithmetic 26 | * (https://www.ietf.org/rfc/rfc1982.txt). 27 | */ 28 | #define TICK_GT(t1, t2) \ 29 | (((t1) < (t2) && (t2) - (t1) > 0xFFFFFFFFu) || \ 30 | ((t1) > (t2) && (t1) - (t2) < 0xFFFFFFFFu)) 31 | 32 | static struct tee_mutex_wait *tee_mutex_wait_get(struct device *dev, 33 | struct tee_mutex_wait_private *priv, u32 key) 34 | { 35 | struct tee_mutex_wait *w; 36 | 37 | mutex_lock(&priv->mu); 38 | 39 | list_for_each_entry(w, &priv->db, link) 40 | if (w->key == key) 41 | goto out; 42 | 43 | w = kmalloc(sizeof(struct tee_mutex_wait), GFP_KERNEL); 44 | if (!w) { 45 | dev_err(dev, "kmalloc failed\n"); 46 | goto out; 47 | } 48 | 49 | init_completion(&w->comp); 50 | mutex_init(&w->mu); 51 | w->wait_after = 0; 52 | w->key = key; 53 | list_add_tail(&w->link, &priv->db); 54 | out: 55 | mutex_unlock(&priv->mu); 56 | return w; 57 | } 58 | 59 | static void tee_mutex_wait_delete_entry(struct tee_mutex_wait *w) 60 | { 61 | list_del(&w->link); 62 | mutex_destroy(&w->mu); 63 | kfree(w); 64 | } 65 | 66 | void tee_mutex_wait_delete(struct device *dev, 67 | struct tee_mutex_wait_private *priv, 68 | u32 key) 69 | { 70 | struct tee_mutex_wait *w; 71 | 72 | mutex_lock(&priv->mu); 73 | 74 | list_for_each_entry(w, &priv->db, link) { 75 | if (w->key == key) { 76 | tee_mutex_wait_delete_entry(w); 77 | break; 78 | } 79 | } 80 | 81 | mutex_unlock(&priv->mu); 82 | } 83 | EXPORT_SYMBOL(tee_mutex_wait_delete); 84 | 85 | void tee_mutex_wait_wakeup(struct device *dev, 86 | struct tee_mutex_wait_private *priv, 87 | u32 key, u32 wait_after) 88 | { 89 | struct tee_mutex_wait *w = tee_mutex_wait_get(dev, priv, key); 90 | 91 | if (!w) 92 | return; 93 | 94 | mutex_lock(&w->mu); 95 | w->wait_after = wait_after; 96 | mutex_unlock(&w->mu); 97 | complete(&w->comp); 98 | } 99 | EXPORT_SYMBOL(tee_mutex_wait_wakeup); 100 | 101 | void tee_mutex_wait_sleep(struct device *dev, 102 | struct tee_mutex_wait_private *priv, 103 | u32 key, u32 wait_tick) 104 | { 105 | struct tee_mutex_wait *w = tee_mutex_wait_get(dev, priv, key); 106 | u32 wait_after; 107 | 108 | if (!w) 109 | return; 110 | 111 | mutex_lock(&w->mu); 112 | wait_after = w->wait_after; 113 | mutex_unlock(&w->mu); 114 | 115 | if (TICK_GT(wait_tick, wait_after)) 116 | wait_for_completion_timeout(&w->comp, HZ); 117 | } 118 | EXPORT_SYMBOL(tee_mutex_wait_sleep); 119 | 120 | int tee_mutex_wait_init(struct tee_mutex_wait_private *priv) 121 | { 122 | mutex_init(&priv->mu); 123 | INIT_LIST_HEAD(&priv->db); 124 | return 0; 125 | } 126 | EXPORT_SYMBOL(tee_mutex_wait_init); 127 | 128 | void tee_mutex_wait_exit(struct tee_mutex_wait_private *priv) 129 | { 130 | /* 131 | * It's the callers responibility to ensure that no one is using 132 | * anything inside priv. 133 | */ 134 | 135 | mutex_destroy(&priv->mu); 136 | while (!list_empty(&priv->db)) { 137 | struct tee_mutex_wait *w = 138 | list_first_entry(&priv->db, 139 | struct tee_mutex_wait, 140 | link); 141 | tee_mutex_wait_delete_entry(w); 142 | } 143 | } 144 | EXPORT_SYMBOL(tee_mutex_wait_exit); 145 | -------------------------------------------------------------------------------- /core/tee_mutex_wait.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Linaro Limited 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #ifndef TEE_MUTEX_WAIT_H 14 | #define TEE_MUTEX_WAIT_H 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | struct tee_mutex_wait_private { 21 | struct mutex mu; 22 | struct list_head db; 23 | }; 24 | 25 | int tee_mutex_wait_init(struct tee_mutex_wait_private *priv); 26 | void tee_mutex_wait_exit(struct tee_mutex_wait_private *priv); 27 | 28 | void tee_mutex_wait_delete(struct device *dev, 29 | struct tee_mutex_wait_private *priv, 30 | u32 key); 31 | void tee_mutex_wait_wakeup(struct device *dev, 32 | struct tee_mutex_wait_private *priv, 33 | u32 key, u32 wait_after); 34 | void tee_mutex_wait_sleep(struct device *dev, 35 | struct tee_mutex_wait_private *priv, 36 | u32 key, u32 wait_tick); 37 | 38 | #endif /*TEE_MUTEX_WAIT_H*/ 39 | -------------------------------------------------------------------------------- /core/tee_shm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | #include "tee_core_priv.h" 22 | #include "tee_shm.h" 23 | 24 | #define INMSG() dev_dbg(_DEV(tee), "%s: >\n", __func__) 25 | #define OUTMSG(val) dev_dbg(_DEV(tee), "%s: < %ld\n", __func__, (long)val) 26 | #define OUTMSGX(val) dev_dbg(_DEV(tee), "%s: < %08x\n",\ 27 | __func__, (unsigned int)(long)val) 28 | 29 | /* TODO 30 | #if (sizeof(TEEC_SharedMemory) != sizeof(tee_shm)) 31 | #error "sizeof(TEEC_SharedMemory) != sizeof(tee_shm))" 32 | #endif 33 | */ 34 | struct tee_shm_attach { 35 | struct sg_table sgt; 36 | enum dma_data_direction dir; 37 | bool is_mapped; 38 | }; 39 | 40 | struct tee_shm *tee_shm_alloc_from_rpc(struct tee *tee, size_t size) 41 | { 42 | struct tee_shm *shm; 43 | 44 | INMSG(); 45 | 46 | mutex_lock(&tee->lock); 47 | shm = tee_shm_alloc(tee, size, TEE_SHM_TEMP | TEE_SHM_FROM_RPC); 48 | if (IS_ERR_OR_NULL(shm)) { 49 | dev_err(_DEV(tee), "%s: buffer allocation failed (%ld)\n", 50 | __func__, PTR_ERR(shm)); 51 | goto out; 52 | } 53 | 54 | tee_inc_stats(&tee->stats[TEE_STATS_SHM_IDX]); 55 | list_add_tail(&shm->entry, &tee->list_rpc_shm); 56 | 57 | shm->ctx = NULL; 58 | 59 | out: 60 | mutex_unlock(&tee->lock); 61 | OUTMSGX(shm); 62 | return shm; 63 | } 64 | 65 | void tee_shm_free_from_rpc(struct tee_shm *shm) 66 | { 67 | struct tee *tee; 68 | 69 | if (shm == NULL) 70 | return; 71 | tee = shm->tee; 72 | mutex_lock(&tee->lock); 73 | if (shm->ctx == NULL) { 74 | tee_dec_stats(&shm->tee->stats[TEE_STATS_SHM_IDX]); 75 | list_del(&shm->entry); 76 | } 77 | 78 | tee_shm_free(shm); 79 | mutex_unlock(&tee->lock); 80 | } 81 | 82 | struct tee_shm *tee_shm_alloc(struct tee *tee, size_t size, uint32_t flags) 83 | { 84 | struct tee_shm *shm; 85 | unsigned long pfn; 86 | unsigned int nr_pages; 87 | struct page *page; 88 | int ret; 89 | 90 | INMSG(); 91 | 92 | shm = tee->ops->alloc(tee, size, flags); 93 | if (IS_ERR_OR_NULL(shm)) { 94 | dev_err(_DEV(tee), 95 | "%s: allocation failed (s=%d,flags=0x%08x) err=%ld\n", 96 | __func__, (int)size, flags, PTR_ERR(shm)); 97 | goto exit; 98 | } 99 | 100 | shm->tee = tee; 101 | 102 | dev_dbg(_DEV(tee), "%s: shm=%p, paddr=%p,s=%d/%d app=\"%s\" pid=%d\n", 103 | __func__, shm, (void *)shm->paddr, (int)shm->size_req, 104 | (int)shm->size_alloc, current->comm, current->pid); 105 | 106 | pfn = shm->paddr >> PAGE_SHIFT; 107 | page = pfn_to_page(pfn); 108 | if (IS_ERR_OR_NULL(page)) { 109 | dev_err(_DEV(tee), "%s: pfn_to_page(%lx) failed\n", 110 | __func__, pfn); 111 | tee->ops->free(shm); 112 | return (struct tee_shm *)page; 113 | } 114 | 115 | /* Only one page of contiguous physical memory */ 116 | nr_pages = 1; 117 | 118 | ret = sg_alloc_table_from_pages(&shm->sgt, &page, 119 | nr_pages, 0, nr_pages * PAGE_SIZE, GFP_KERNEL); 120 | if (IS_ERR_VALUE(ret)) { 121 | dev_err(_DEV(tee), "%s: sg_alloc_table_from_pages() failed\n", 122 | __func__); 123 | tee->ops->free(shm); 124 | shm = ERR_PTR(ret); 125 | } 126 | exit: 127 | OUTMSGX(shm); 128 | return shm; 129 | } 130 | 131 | void tee_shm_free(struct tee_shm *shm) 132 | { 133 | struct tee *tee; 134 | 135 | if (IS_ERR_OR_NULL(shm)) 136 | return; 137 | tee = shm->tee; 138 | if (tee == NULL) 139 | pr_warn("invalid call to tee_shm_free(%p): NULL tee\n", shm); 140 | else if (shm->tee == NULL) 141 | dev_warn(_DEV(tee), "tee_shm_free(%p): NULL tee\n", shm); 142 | else { 143 | sg_free_table(&shm->sgt); 144 | shm->tee->ops->free(shm); 145 | } 146 | } 147 | 148 | static int _tee_shm_attach_dma_buf(struct dma_buf *dmabuf, 149 | struct device *dev, 150 | struct dma_buf_attachment *attach) 151 | { 152 | struct tee_shm_attach *tee_shm_attach; 153 | struct tee_shm *shm; 154 | struct tee *tee; 155 | 156 | shm = dmabuf->priv; 157 | tee = shm->tee; 158 | 159 | INMSG(); 160 | 161 | tee_shm_attach = devm_kzalloc(_DEV(tee), 162 | sizeof(*tee_shm_attach), GFP_KERNEL); 163 | if (!tee_shm_attach) { 164 | OUTMSG(-ENOMEM); 165 | return -ENOMEM; 166 | } 167 | 168 | tee_shm_attach->dir = DMA_NONE; 169 | attach->priv = tee_shm_attach; 170 | 171 | OUTMSG(0); 172 | return 0; 173 | } 174 | 175 | static void _tee_shm_detach_dma_buf(struct dma_buf *dmabuf, 176 | struct dma_buf_attachment *attach) 177 | { 178 | struct tee_shm_attach *tee_shm_attach = attach->priv; 179 | struct sg_table *sgt; 180 | struct tee_shm *shm; 181 | struct tee *tee; 182 | 183 | shm = dmabuf->priv; 184 | tee = shm->tee; 185 | 186 | INMSG(); 187 | 188 | if (!tee_shm_attach) { 189 | OUTMSG(0); 190 | return; 191 | } 192 | 193 | sgt = &tee_shm_attach->sgt; 194 | 195 | if (tee_shm_attach->dir != DMA_NONE) 196 | dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, 197 | tee_shm_attach->dir); 198 | 199 | sg_free_table(sgt); 200 | devm_kfree(_DEV(tee), tee_shm_attach); 201 | attach->priv = NULL; 202 | OUTMSG(0); 203 | } 204 | 205 | static struct sg_table *_tee_shm_dma_buf_map_dma_buf( 206 | struct dma_buf_attachment *attach, enum dma_data_direction dir) 207 | { 208 | struct tee_shm_attach *tee_shm_attach = attach->priv; 209 | struct tee_shm *tee_shm = attach->dmabuf->priv; 210 | struct sg_table *sgt = NULL; 211 | struct scatterlist *rd, *wr; 212 | unsigned int i; 213 | int nents, ret; 214 | struct tee *tee; 215 | 216 | tee = tee_shm->tee; 217 | 218 | INMSG(); 219 | 220 | /* just return current sgt if already requested. */ 221 | if (tee_shm_attach->dir == dir && tee_shm_attach->is_mapped) { 222 | OUTMSGX(&tee_shm_attach->sgt); 223 | return &tee_shm_attach->sgt; 224 | } 225 | 226 | sgt = &tee_shm_attach->sgt; 227 | 228 | ret = sg_alloc_table(sgt, tee_shm->sgt.orig_nents, GFP_KERNEL); 229 | if (ret) { 230 | dev_err(_DEV(tee), "failed to alloc sgt.\n"); 231 | return ERR_PTR(-ENOMEM); 232 | } 233 | 234 | rd = tee_shm->sgt.sgl; 235 | wr = sgt->sgl; 236 | for (i = 0; i < sgt->orig_nents; ++i) { 237 | sg_set_page(wr, sg_page(rd), rd->length, rd->offset); 238 | rd = sg_next(rd); 239 | wr = sg_next(wr); 240 | } 241 | 242 | if (dir != DMA_NONE) { 243 | nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir); 244 | if (!nents) { 245 | dev_err(_DEV(tee), "failed to map sgl with iommu.\n"); 246 | sg_free_table(sgt); 247 | sgt = ERR_PTR(-EIO); 248 | goto err_unlock; 249 | } 250 | } 251 | 252 | tee_shm_attach->is_mapped = true; 253 | tee_shm_attach->dir = dir; 254 | attach->priv = tee_shm_attach; 255 | 256 | err_unlock: 257 | OUTMSGX(sgt); 258 | return sgt; 259 | } 260 | 261 | static void _tee_shm_dma_buf_unmap_dma_buf(struct dma_buf_attachment *attach, 262 | struct sg_table *table, 263 | enum dma_data_direction dir) 264 | { 265 | return; 266 | } 267 | 268 | static void _tee_shm_dma_buf_release(struct dma_buf *dmabuf) 269 | { 270 | struct tee_shm *shm = dmabuf->priv; 271 | struct tee_context *ctx; 272 | struct tee *tee; 273 | 274 | tee = shm->ctx->tee; 275 | 276 | INMSG(); 277 | 278 | ctx = shm->ctx; 279 | dev_dbg(_DEV(ctx->tee), "%s: shm=%p, paddr=%p,s=%d/%d app=\"%s\" pid=%d\n", 280 | __func__, shm, (void *)shm->paddr, (int)shm->size_req, 281 | (int)shm->size_alloc, current->comm, current->pid); 282 | 283 | tee_shm_free_io(shm); 284 | 285 | OUTMSG(0); 286 | } 287 | 288 | static int _tee_shm_dma_buf_mmap(struct dma_buf *dmabuf, 289 | struct vm_area_struct *vma) 290 | { 291 | struct tee_shm *shm = dmabuf->priv; 292 | size_t size = vma->vm_end - vma->vm_start; 293 | struct tee *tee; 294 | int ret; 295 | pgprot_t prot; 296 | unsigned long pfn; 297 | 298 | tee = shm->ctx->tee; 299 | 300 | pfn = shm->paddr >> PAGE_SHIFT; 301 | 302 | INMSG(); 303 | 304 | if (shm->flags & TEE_SHM_CACHED) 305 | prot = vma->vm_page_prot; 306 | else 307 | prot = pgprot_noncached(vma->vm_page_prot); 308 | 309 | ret = 310 | remap_pfn_range(vma, vma->vm_start, pfn, size, prot); 311 | if (!ret) 312 | vma->vm_private_data = (void *)shm; 313 | 314 | dev_dbg(_DEV(shm->ctx->tee), "%s: map the shm (p@=%p,s=%dKiB) => %x\n", 315 | __func__, (void *)shm->paddr, (int)size / 1024, 316 | (unsigned int)vma->vm_start); 317 | 318 | OUTMSG(ret); 319 | return ret; 320 | } 321 | 322 | static void *_tee_shm_dma_buf_kmap_atomic(struct dma_buf *dmabuf, 323 | unsigned long pgnum) 324 | { 325 | return NULL; 326 | } 327 | 328 | static void *_tee_shm_dma_buf_kmap(struct dma_buf *db, unsigned long pgnum) 329 | { 330 | struct tee_shm *shm = db->priv; 331 | 332 | dev_dbg(_DEV(shm->ctx->tee), "%s: kmap the shm (p@=%p, v@=%p, s=%zdKiB)\n", 333 | __func__, (void *)shm->paddr, (void *)shm->kaddr, 334 | shm->size_alloc / 1024); 335 | /* 336 | * A this stage, a shm allocated by the tee 337 | * must be have a kernel address 338 | */ 339 | return shm->kaddr; 340 | } 341 | 342 | static void _tee_shm_dma_buf_kunmap( 343 | struct dma_buf *db, unsigned long pfn, void *kaddr) 344 | { 345 | /* unmap is done at the de init of the shm pool */ 346 | } 347 | 348 | struct dma_buf_ops _tee_shm_dma_buf_ops = { 349 | .attach = _tee_shm_attach_dma_buf, 350 | .detach = _tee_shm_detach_dma_buf, 351 | .map_dma_buf = _tee_shm_dma_buf_map_dma_buf, 352 | .unmap_dma_buf = _tee_shm_dma_buf_unmap_dma_buf, 353 | .release = _tee_shm_dma_buf_release, 354 | .kmap_atomic = _tee_shm_dma_buf_kmap_atomic, 355 | .kmap = _tee_shm_dma_buf_kmap, 356 | .kunmap = _tee_shm_dma_buf_kunmap, 357 | .mmap = _tee_shm_dma_buf_mmap, 358 | }; 359 | 360 | /******************************************************************************/ 361 | 362 | static int export_buf(struct tee *tee, struct tee_shm *shm, int *export) 363 | { 364 | struct dma_buf *dmabuf; 365 | int ret = 0; 366 | /* Temporary fix to support both older and newer kernel versions. */ 367 | #if defined(DEFINE_DMA_BUF_EXPORT_INFO) 368 | DEFINE_DMA_BUF_EXPORT_INFO(exp_info); 369 | 370 | exp_info.priv = shm; 371 | exp_info.ops = &_tee_shm_dma_buf_ops; 372 | exp_info.size = shm->size_alloc; 373 | exp_info.flags = O_RDWR; 374 | 375 | dmabuf = dma_buf_export(&exp_info); 376 | #else 377 | dmabuf = dma_buf_export(shm, &_tee_shm_dma_buf_ops, shm->size_alloc, 378 | O_RDWR, 0); 379 | #endif 380 | if (IS_ERR_OR_NULL(dmabuf)) { 381 | dev_err(_DEV(tee), "%s: dmabuf: couldn't export buffer (%ld)\n", 382 | __func__, PTR_ERR(dmabuf)); 383 | ret = -EINVAL; 384 | goto out; 385 | } 386 | 387 | *export = dma_buf_fd(dmabuf, O_CLOEXEC); 388 | out: 389 | OUTMSG(ret); 390 | return ret; 391 | } 392 | 393 | int tee_shm_alloc_io(struct tee_context *ctx, struct tee_shm_io *shm_io) 394 | { 395 | struct tee_shm *shm; 396 | struct tee *tee = ctx->tee; 397 | int ret; 398 | 399 | INMSG(); 400 | 401 | if (ctx->usr_client) 402 | shm_io->fd_shm = 0; 403 | 404 | mutex_lock(&tee->lock); 405 | shm = tee_shm_alloc(tee, shm_io->size, shm_io->flags); 406 | if (IS_ERR_OR_NULL(shm)) { 407 | dev_err(_DEV(tee), "%s: buffer allocation failed (%ld)\n", 408 | __func__, PTR_ERR(shm)); 409 | ret = PTR_ERR(shm); 410 | goto out; 411 | } 412 | 413 | if (ctx->usr_client) { 414 | ret = export_buf(tee, shm, &shm_io->fd_shm); 415 | if (ret) { 416 | tee_shm_free(shm); 417 | ret = -ENOMEM; 418 | goto out; 419 | } 420 | 421 | shm->flags |= TEEC_MEM_DMABUF; 422 | } 423 | 424 | shm->ctx = ctx; 425 | shm->dev = get_device(_DEV(tee)); 426 | ret = tee_get(tee); 427 | BUG_ON(ret); /* tee_core_get must not issue */ 428 | tee_context_get(ctx); 429 | 430 | tee_inc_stats(&tee->stats[TEE_STATS_SHM_IDX]); 431 | list_add_tail(&shm->entry, &ctx->list_shm); 432 | out: 433 | mutex_unlock(&tee->lock); 434 | OUTMSG(ret); 435 | return ret; 436 | } 437 | 438 | void tee_shm_free_io(struct tee_shm *shm) 439 | { 440 | struct tee_context *ctx = shm->ctx; 441 | struct tee *tee = ctx->tee; 442 | struct device *dev = shm->dev; 443 | 444 | mutex_lock(&ctx->tee->lock); 445 | tee_dec_stats(&tee->stats[TEE_STATS_SHM_IDX]); 446 | list_del(&shm->entry); 447 | 448 | tee_shm_free(shm); 449 | tee_put(ctx->tee); 450 | tee_context_put(ctx); 451 | if (dev) 452 | put_device(dev); 453 | mutex_unlock(&ctx->tee->lock); 454 | } 455 | 456 | /* Buffer allocated by rpc from fw and to be accessed by the user 457 | * Not need to be registered as it is not allocated by the user */ 458 | int tee_shm_fd_for_rpc(struct tee_context *ctx, struct tee_shm_io *shm_io) 459 | { 460 | struct tee_shm *shm = NULL; 461 | struct tee *tee = ctx->tee; 462 | int ret; 463 | struct list_head *pshm; 464 | 465 | INMSG(); 466 | 467 | shm_io->fd_shm = 0; 468 | 469 | mutex_lock(&tee->lock); 470 | if (!list_empty(&tee->list_rpc_shm)) { 471 | list_for_each(pshm, &tee->list_rpc_shm) { 472 | shm = list_entry(pshm, struct tee_shm, entry); 473 | if ((void *)shm->paddr == shm_io->buffer) 474 | goto found; 475 | } 476 | } 477 | 478 | dev_err(_DEV(tee), "Can't find shm for %p\n", (void *)shm_io->buffer); 479 | ret = -ENOMEM; 480 | goto out; 481 | 482 | found: 483 | ret = export_buf(tee, shm, &shm_io->fd_shm); 484 | if (ret) { 485 | ret = -ENOMEM; 486 | goto out; 487 | } 488 | 489 | shm->ctx = ctx; 490 | list_move(&shm->entry, &ctx->list_shm); 491 | 492 | shm->dev = get_device(_DEV(tee)); 493 | ret = tee_get(tee); 494 | BUG_ON(ret); 495 | tee_context_get(ctx); 496 | 497 | BUG_ON(!tee->ops->shm_inc_ref(shm)); 498 | out: 499 | mutex_unlock(&tee->lock); 500 | OUTMSG(ret); 501 | return ret; 502 | } 503 | 504 | /******************************************************************************/ 505 | 506 | static int tee_shm_db_get(struct tee *tee, struct tee_shm *shm, int fd, 507 | unsigned int flags, size_t size, int offset) 508 | { 509 | struct tee_shm_dma_buf *sdb; 510 | struct dma_buf *dma_buf; 511 | int ret = 0; 512 | 513 | dev_dbg(_DEV(tee), "%s: > fd=%d flags=%08x\n", __func__, fd, flags); 514 | 515 | dma_buf = dma_buf_get(fd); 516 | if (IS_ERR(dma_buf)) { 517 | ret = PTR_ERR(dma_buf); 518 | goto exit; 519 | } 520 | 521 | sdb = kzalloc(sizeof(*sdb), GFP_KERNEL); 522 | if (IS_ERR_OR_NULL(sdb)) { 523 | dev_err(_DEV(tee), "can't alloc tee_shm_dma_buf\n"); 524 | ret = PTR_ERR(sdb); 525 | goto buf_put; 526 | } 527 | shm->sdb = sdb; 528 | 529 | if (dma_buf->size < size + offset) { 530 | dev_err(_DEV(tee), "dma_buf too small %zd < %zd + %d\n", 531 | dma_buf->size, size, offset); 532 | ret = -EINVAL; 533 | goto free_sdb; 534 | } 535 | 536 | sdb->attach = dma_buf_attach(dma_buf, _DEV(tee)); 537 | if (IS_ERR_OR_NULL(sdb->attach)) { 538 | ret = PTR_ERR(sdb->attach); 539 | goto free_sdb; 540 | } 541 | 542 | sdb->sgt = dma_buf_map_attachment(sdb->attach, DMA_NONE); 543 | if (IS_ERR_OR_NULL(sdb->sgt)) { 544 | ret = PTR_ERR(sdb->sgt); 545 | goto buf_detach; 546 | } 547 | 548 | if (sg_nents(sdb->sgt->sgl) != 1) { 549 | ret = -EINVAL; 550 | goto buf_unmap; 551 | } 552 | 553 | shm->paddr = sg_phys(sdb->sgt->sgl) + offset; 554 | if (dma_buf->ops->attach == _tee_shm_attach_dma_buf) 555 | sdb->tee_allocated = true; 556 | else 557 | sdb->tee_allocated = false; 558 | 559 | shm->flags |= TEEC_MEM_DMABUF; 560 | 561 | dev_dbg(_DEV(tee), "fd=%d @p=%p is_tee=%d db=%p\n", fd, 562 | (void *)shm->paddr, sdb->tee_allocated, dma_buf); 563 | goto exit; 564 | 565 | buf_unmap: 566 | dma_buf_unmap_attachment(sdb->attach, sdb->sgt, DMA_NONE); 567 | buf_detach: 568 | dma_buf_detach(dma_buf, sdb->attach); 569 | free_sdb: 570 | kfree(sdb); 571 | buf_put: 572 | dma_buf_put(dma_buf); 573 | exit: 574 | OUTMSG(ret); 575 | return ret; 576 | } 577 | 578 | #ifdef VA_GET_ENABLED 579 | static unsigned int tee_shm_get_phy_from_kla( 580 | struct mm_struct *mm, unsigned int kla) 581 | { 582 | pgd_t *pgd; 583 | pud_t *pud; 584 | pmd_t *pmd; 585 | pte_t *ptep, pte; 586 | unsigned int pa = 0; 587 | 588 | /* stolen from kernel3.10:mm/memory.c:__follow_pte */ 589 | 590 | pgd = pgd_offset(mm, kla); 591 | if (pgd_none(*pgd) || pgd_bad(*pgd)) 592 | return 0; 593 | 594 | pud = pud_offset(pgd, kla); 595 | if (pud_none(*pud) || pud_bad(*pud)) 596 | return 0; 597 | 598 | pmd = pmd_offset(pud, kla); 599 | VM_BUG_ON(pmd_trans_huge(*pmd)); 600 | if (pmd_none(*pmd) || pmd_bad(*pmd)) 601 | return 0; 602 | 603 | /* We cannot handle huge page PFN maps. 604 | * Luckily they don't exist. */ 605 | if (pmd_huge(*pmd)) 606 | return 0; 607 | 608 | ptep = pte_offset_map(pmd, kla); 609 | 610 | if (!ptep) 611 | return 0; 612 | 613 | pte = *ptep; 614 | 615 | if (pte_present(pte)) 616 | pa = __pa(page_address(pte_page(pte))); 617 | 618 | if (!pa) 619 | return 0; 620 | 621 | return pa; 622 | 623 | } 624 | 625 | static int tee_shm_va_get(struct tee_context *ctx, struct tee_shm *shm, 626 | void *buffer, unsigned int flags, size_t size, int offset) 627 | { 628 | int ret = 0; 629 | struct mm_struct *mm = current->mm; 630 | unsigned long va = (unsigned long)buffer; 631 | unsigned int virt_base = (va / PAGE_SIZE) * PAGE_SIZE; 632 | unsigned int offset_in_page = va - virt_base; 633 | unsigned int offset_total = offset_in_page + offset; 634 | struct vm_area_struct *vma; 635 | struct tee *tee = ctx->tee; 636 | 637 | dev_dbg(_DEV(tee), "%s: > %p\n", __func__, buffer); 638 | /* if the caller is the kernel api, active_mm is mm */ 639 | if (!mm) 640 | mm = current->active_mm; 641 | 642 | BUG_ON(!mm); 643 | 644 | vma = find_vma(mm, virt_base); 645 | 646 | if (vma) { 647 | unsigned long pfn; 648 | /* It's a VMA => consider it a a user address */ 649 | 650 | if (follow_pfn(vma, virt_base, &pfn)) { 651 | dev_err(_DEV(tee), "%s can't get pfn for %p\n", 652 | __func__, buffer); 653 | ret = -EINVAL; 654 | goto out; 655 | } 656 | 657 | shm->paddr = PFN_PHYS(pfn) + offset_total; 658 | 659 | if (vma->vm_end - vma->vm_start - offset_total < size) { 660 | dev_err(_DEV(tee), "%s %p:%x not big enough: %lx - %d < %x\n", 661 | __func__, buffer, shm->paddr, 662 | vma->vm_end - vma->vm_start, 663 | offset_total, size); 664 | shm->paddr = 0; 665 | ret = -EINVAL; 666 | goto out; 667 | } 668 | } else if (!ctx->usr_client) { 669 | /* It's not a VMA => consider it as a kernel address 670 | * And look if it's an internal known phys addr 671 | * Note: virt_to_phys is not usable since it can be a direct 672 | * map or a vremap address 673 | */ 674 | unsigned int phys_base; 675 | int nb_page = (PAGE_SIZE - 1 + size + offset_total) / PAGE_SIZE; 676 | int i; 677 | 678 | spin_lock(&mm->page_table_lock); 679 | phys_base = tee_shm_get_phy_from_kla(mm, virt_base); 680 | 681 | if (!phys_base) { 682 | spin_unlock(&mm->page_table_lock); 683 | dev_err(_DEV(tee), "%s can't get physical address for %p\n", 684 | __func__, buffer); 685 | goto err; 686 | } 687 | 688 | /* Check continuity on size */ 689 | for (i = 1; i < nb_page; i++) { 690 | unsigned int pa = tee_shm_get_phy_from_kla(mm, 691 | virt_base + i*PAGE_SIZE); 692 | if (pa != phys_base + i*PAGE_SIZE) { 693 | spin_unlock(&mm->page_table_lock); 694 | dev_err(_DEV(tee), "%s %p:%x not big enough: %lx - %d < %x\n", 695 | __func__, buffer, phys_base, 696 | i*PAGE_SIZE, 697 | offset_total, size); 698 | goto err; 699 | } 700 | } 701 | spin_unlock(&mm->page_table_lock); 702 | 703 | shm->paddr = phys_base + offset_total; 704 | goto out; 705 | err: 706 | ret = -EINVAL; 707 | } 708 | 709 | out: 710 | dev_dbg(_DEV(tee), "%s: < %d shm=%p vaddr=%p paddr=%x\n", 711 | __func__, ret, (void *)shm, buffer, shm->paddr); 712 | return ret; 713 | } 714 | #endif 715 | 716 | struct tee_shm *tee_shm_get(struct tee_context *ctx, TEEC_SharedMemory *c_shm, 717 | size_t size, int offset) 718 | { 719 | struct tee_shm *shm; 720 | struct tee *tee = ctx->tee; 721 | int ret; 722 | 723 | dev_dbg(_DEV(tee), "%s: > fd=%d flags=%08x\n", 724 | __func__, c_shm->d.fd, c_shm->flags); 725 | 726 | mutex_lock(&tee->lock); 727 | shm = kzalloc(sizeof(*shm), GFP_KERNEL); 728 | if (IS_ERR_OR_NULL(shm)) { 729 | dev_err(_DEV(tee), "can't alloc tee_shm\n"); 730 | ret = -ENOMEM; 731 | goto err; 732 | } 733 | 734 | shm->ctx = ctx; 735 | shm->tee = tee; 736 | shm->dev = _DEV(tee); 737 | shm->flags = c_shm->flags | TEE_SHM_MEMREF; 738 | shm->size_req = size; 739 | shm->size_alloc = 0; 740 | 741 | if (c_shm->flags & TEEC_MEM_KAPI) { 742 | struct tee_shm *kc_shm = (struct tee_shm *)c_shm->d.ptr; 743 | 744 | if (!kc_shm) { 745 | dev_err(_DEV(tee), "kapi fd null\n"); 746 | ret = -EINVAL; 747 | goto err; 748 | } 749 | shm->paddr = kc_shm->paddr; 750 | 751 | if (kc_shm->size_alloc < size + offset) { 752 | dev_err(_DEV(tee), "kapi buff too small %zd < %zd + %d\n", 753 | kc_shm->size_alloc, size, offset); 754 | ret = -EINVAL; 755 | goto err; 756 | } 757 | 758 | dev_dbg(_DEV(tee), "fd=%d @p=%p\n", 759 | c_shm->d.fd, (void *)shm->paddr); 760 | } else if (c_shm->d.fd) { 761 | ret = tee_shm_db_get(tee, shm, 762 | c_shm->d.fd, c_shm->flags, size, offset); 763 | if (ret) 764 | goto err; 765 | } else if (!c_shm->buffer) { 766 | dev_dbg(_DEV(tee), "null buffer, pass 'as is'\n"); 767 | } else { 768 | #ifdef VA_GET_ENABLED 769 | ret = tee_shm_va_get(ctx, shm, 770 | c_shm->buffer, c_shm->flags, size, offset); 771 | if (ret) 772 | goto err; 773 | #else 774 | ret = -EINVAL; 775 | goto err; 776 | #endif 777 | } 778 | 779 | mutex_unlock(&tee->lock); 780 | OUTMSGX(shm); 781 | return shm; 782 | 783 | err: 784 | kfree(shm); 785 | mutex_unlock(&tee->lock); 786 | OUTMSGX(ERR_PTR(ret)); 787 | return ERR_PTR(ret); 788 | } 789 | 790 | void tee_shm_put(struct tee_context *ctx, struct tee_shm *shm) 791 | { 792 | struct tee *tee = ctx->tee; 793 | 794 | dev_dbg(_DEV(tee), "%s: > shm=%p flags=%08x paddr=%p\n", 795 | __func__, (void *)shm, shm->flags, (void *)shm->paddr); 796 | 797 | BUG_ON(!shm); 798 | BUG_ON(!(shm->flags & TEE_SHM_MEMREF)); 799 | 800 | mutex_lock(&tee->lock); 801 | if (shm->flags & TEEC_MEM_DMABUF) { 802 | struct tee_shm_dma_buf *sdb; 803 | struct dma_buf *dma_buf; 804 | 805 | sdb = shm->sdb; 806 | dma_buf = sdb->attach->dmabuf; 807 | 808 | dev_dbg(_DEV(tee), "%s: db=%p\n", __func__, (void *)dma_buf); 809 | 810 | dma_buf_unmap_attachment(sdb->attach, sdb->sgt, DMA_NONE); 811 | dma_buf_detach(dma_buf, sdb->attach); 812 | dma_buf_put(dma_buf); 813 | 814 | kfree(sdb); 815 | sdb = 0; 816 | } 817 | 818 | kfree(shm); 819 | mutex_unlock(&tee->lock); 820 | OUTMSG(0); 821 | } 822 | 823 | -------------------------------------------------------------------------------- /core/tee_shm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #ifndef __TEE_SHM_H__ 14 | #define __TEE_SHM_H__ 15 | 16 | #include 17 | struct tee_context; 18 | struct tee_shm; 19 | struct tee_shm_io; 20 | struct tee; 21 | 22 | int tee_shm_alloc_io(struct tee_context *ctx, struct tee_shm_io *shm_io); 23 | void tee_shm_free_io(struct tee_shm *shm); 24 | 25 | int tee_shm_fd_for_rpc(struct tee_context *ctx, struct tee_shm_io *shm_io); 26 | 27 | struct tee_shm *tee_shm_alloc(struct tee *tee, size_t size, uint32_t flags); 28 | void tee_shm_free(struct tee_shm *shm); 29 | 30 | struct tee_shm *tee_shm_get(struct tee_context *ctx, TEEC_SharedMemory *c_shm, 31 | size_t size, int offset); 32 | void tee_shm_put(struct tee_context *ctx, struct tee_shm *shm); 33 | 34 | #endif /* __TEE_SHM_H__ */ 35 | -------------------------------------------------------------------------------- /core/tee_supp_com.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "tee_shm.h" 25 | #include "tee_core.h" 26 | #include "tee_supp_com.h" 27 | 28 | #define TEE_RPC_BUFFER 0x00000001 29 | #define TEE_RPC_VALUE 0x00000002 30 | 31 | enum teec_rpc_result tee_supp_cmd(struct tee *tee, 32 | uint32_t id, void *data, size_t datalen) 33 | { 34 | struct tee_rpc *rpc = tee->rpc; 35 | enum teec_rpc_result res = TEEC_RPC_FAIL; 36 | size_t size; 37 | struct task_struct *task = current; 38 | 39 | dev_dbg(tee->dev, "> tgid:[%d] id:[0x%08x]\n", task->tgid, id); 40 | 41 | if (atomic_read(&rpc->used) == 0) { 42 | dev_err(tee->dev, "%s: ERROR Supplicant application NOT ready\n" 43 | , __func__); 44 | goto out; 45 | } 46 | 47 | switch (id) { 48 | case TEE_RPC_ICMD_ALLOCATE: 49 | { 50 | struct tee_rpc_alloc *alloc; 51 | struct tee_shm *shmint; 52 | 53 | alloc = (struct tee_rpc_alloc *)data; 54 | size = alloc->size; 55 | memset(alloc, 0, sizeof(struct tee_rpc_alloc)); 56 | shmint = tee_shm_alloc_from_rpc(tee, size); 57 | if (IS_ERR_OR_NULL(shmint)) 58 | break; 59 | 60 | alloc->size = size; 61 | alloc->data = (void *)shmint->paddr; 62 | alloc->shm = shmint; 63 | res = TEEC_RPC_OK; 64 | 65 | break; 66 | } 67 | case TEE_RPC_ICMD_FREE: 68 | { 69 | struct tee_rpc_free *free; 70 | 71 | free = (struct tee_rpc_free *)data; 72 | tee_shm_free_from_rpc(free->shm); 73 | res = TEEC_RPC_OK; 74 | break; 75 | } 76 | case TEE_RPC_ICMD_INVOKE: 77 | { 78 | if (sizeof(rpc->commToUser) < datalen) 79 | break; 80 | 81 | /* 82 | * Other threads blocks here until we've copied our 83 | * answer from the supplicant 84 | */ 85 | mutex_lock(&rpc->thrd_mutex); 86 | 87 | mutex_lock(&rpc->outsync); 88 | memcpy(&rpc->commToUser, data, datalen); 89 | mutex_unlock(&rpc->outsync); 90 | 91 | dev_dbg(tee->dev, 92 | "Supplicant Cmd: %x. Give hand to supplicant\n", 93 | rpc->commToUser.cmd); 94 | 95 | up(&rpc->datatouser); 96 | 97 | down(&rpc->datafromuser); 98 | 99 | dev_dbg(tee->dev, 100 | "Supplicant Cmd: %x. Give hand to fw\n", 101 | rpc->commToUser.cmd); 102 | 103 | mutex_lock(&rpc->insync); 104 | memcpy(data, &rpc->commFromUser, datalen); 105 | mutex_unlock(&rpc->insync); 106 | 107 | mutex_unlock(&rpc->thrd_mutex); 108 | 109 | res = TEEC_RPC_OK; 110 | 111 | break; 112 | } 113 | default: 114 | /* not supported */ 115 | break; 116 | } 117 | 118 | out: 119 | dev_dbg(tee->dev, "< res: [%d]\n", res); 120 | 121 | return res; 122 | } 123 | EXPORT_SYMBOL(tee_supp_cmd); 124 | 125 | ssize_t tee_supp_read(struct file *filp, char __user *buffer, 126 | size_t length, loff_t *offset) 127 | { 128 | struct tee_context *ctx = (struct tee_context *)(filp->private_data); 129 | struct tee *tee; 130 | struct tee_rpc *rpc; 131 | struct task_struct *task = current; 132 | int ret; 133 | 134 | BUG_ON(!ctx); 135 | tee = ctx->tee; 136 | BUG_ON(!tee); 137 | BUG_ON(!tee->dev); 138 | BUG_ON(!tee->rpc); 139 | 140 | dev_dbg(tee->dev, "> ctx %p\n", ctx); 141 | 142 | rpc = tee->rpc; 143 | 144 | if (atomic_read(&rpc->used) == 0) { 145 | dev_err(tee->dev, "%s: ERROR Supplicant application NOT ready\n" 146 | , __func__); 147 | ret = -EPERM; 148 | goto out; 149 | } 150 | 151 | if (down_interruptible(&rpc->datatouser)) 152 | return -ERESTARTSYS; 153 | 154 | dev_dbg(tee->dev, "> tgid:[%d]\n", task->tgid); 155 | 156 | mutex_lock(&rpc->outsync); 157 | 158 | ret = 159 | sizeof(rpc->commToUser) - sizeof(rpc->commToUser.cmds) + 160 | sizeof(rpc->commToUser.cmds[0]) * rpc->commToUser.nbr_bf; 161 | if (length < ret) { 162 | ret = -EINVAL; 163 | } else { 164 | if (copy_to_user(buffer, &rpc->commToUser, ret)) { 165 | dev_err(tee->dev, 166 | "[%s] error, copy_to_user failed!\n", __func__); 167 | ret = -EINVAL; 168 | } 169 | } 170 | 171 | mutex_unlock(&rpc->outsync); 172 | 173 | out: 174 | dev_dbg(tee->dev, "< [%d]\n", ret); 175 | return ret; 176 | } 177 | 178 | ssize_t tee_supp_write(struct file *filp, const char __user *buffer, 179 | size_t length, loff_t *offset) 180 | { 181 | struct tee_context *ctx = (struct tee_context *)(filp->private_data); 182 | struct tee *tee; 183 | struct tee_rpc *rpc; 184 | struct task_struct *task = current; 185 | int ret = 0; 186 | 187 | BUG_ON(!ctx); 188 | BUG_ON(!ctx->tee); 189 | BUG_ON(!ctx->tee->rpc); 190 | tee = ctx->tee; 191 | rpc = tee->rpc; 192 | dev_dbg(tee->dev, "> tgid:[%d]\n", task->tgid); 193 | 194 | if (atomic_read(&rpc->used) == 0) { 195 | dev_err(tee->dev, "%s: ERROR Supplicant application NOT ready\n" 196 | , __func__); 197 | goto out; 198 | } 199 | 200 | if (length > 0 && length < sizeof(rpc->commFromUser)) { 201 | uint32_t i; 202 | 203 | mutex_lock(&rpc->insync); 204 | 205 | if (copy_from_user(&rpc->commFromUser, buffer, length)) { 206 | dev_err(tee->dev, 207 | "%s: ERROR, tee_session copy_from_user failed\n", 208 | __func__); 209 | mutex_unlock(&rpc->insync); 210 | ret = -EINVAL; 211 | goto out; 212 | } 213 | 214 | /* Translate virtual address of caller into physical address */ 215 | for (i = 0; i < rpc->commFromUser.nbr_bf; i++) { 216 | if (rpc->commFromUser.cmds[i].type == TEE_RPC_BUFFER 217 | && rpc->commFromUser.cmds[i].buffer) { 218 | struct vm_area_struct *vma = 219 | find_vma(current->mm, 220 | (unsigned long)rpc-> 221 | commFromUser.cmds[i].buffer); 222 | if (vma != NULL) { 223 | struct tee_shm *shm = 224 | vma->vm_private_data; 225 | BUG_ON(!shm); 226 | dev_dbg(tee->dev, 227 | "%d gid2pa(0x%p => %x)\n", i, 228 | rpc->commFromUser.cmds[i]. 229 | buffer, 230 | (unsigned int)shm->paddr); 231 | rpc->commFromUser.cmds[i].buffer = 232 | (void *)shm->paddr; 233 | } else 234 | dev_dbg(tee->dev, 235 | " gid2pa(0x%p => NULL\n)", 236 | rpc->commFromUser.cmds[i]. 237 | buffer); 238 | } 239 | } 240 | 241 | mutex_unlock(&rpc->insync); 242 | up(&rpc->datafromuser); 243 | ret = length; 244 | } 245 | 246 | out: 247 | dev_dbg(tee->dev, "< [%d]\n", ret); 248 | return ret; 249 | } 250 | 251 | int tee_supp_init(struct tee *tee) 252 | { 253 | struct tee_rpc *rpc = 254 | devm_kzalloc(tee->dev, sizeof(struct tee_rpc), GFP_KERNEL); 255 | if (!rpc) { 256 | dev_err(tee->dev, "%s: can't allocate tee_rpc structure\n", 257 | __func__); 258 | return -ENOMEM; 259 | } 260 | 261 | rpc->datafromuser = (struct semaphore) 262 | __SEMAPHORE_INITIALIZER(rpc->datafromuser, 0); 263 | rpc->datatouser = (struct semaphore) 264 | __SEMAPHORE_INITIALIZER(rpc->datatouser, 0); 265 | mutex_init(&rpc->thrd_mutex); 266 | mutex_init(&rpc->outsync); 267 | mutex_init(&rpc->insync); 268 | atomic_set(&rpc->used, 0); 269 | tee->rpc = rpc; 270 | return 0; 271 | } 272 | 273 | void tee_supp_deinit(struct tee *tee) 274 | { 275 | devm_kfree(tee->dev, tee->rpc); 276 | tee->rpc = NULL; 277 | } 278 | -------------------------------------------------------------------------------- /core/tee_supp_com.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #ifndef TEE_SUPP_COMM_H 14 | #define TEE_SUPP_COMM_H 15 | 16 | #define TEE_RPC_ICMD_ALLOCATE 0x1001 17 | #define TEE_RPC_ICMD_FREE 0x1002 18 | #define TEE_RPC_ICMD_INVOKE 0x1003 19 | 20 | #define TEE_RPC_NBR_BUFF 1 21 | #define TEE_RPC_DATA_SIZE 64 22 | #define TEE_RPC_BUFFER_NUMBER 5 23 | 24 | #define TEE_RPC_STATE_IDLE 0x00 25 | #define TEE_RPC_STATE_ACTIVE 0x01 26 | 27 | /* Keep aligned with optee_client (user space) */ 28 | #define TEE_RPC_BUFFER 0x00000001 29 | #define TEE_RPC_VALUE 0x00000002 30 | #define TEE_RPC_LOAD_TA 0x10000001 31 | /* 32 | * Handled within the driver only 33 | * Keep aligned with optee_os (secure space) 34 | */ 35 | #define TEE_RPC_MUTEX_WAIT 0x20000000 36 | #define TEE_RPC_WAIT_QUEUE_SLEEP 0x20000001 37 | #define TEE_RPC_WAIT_QUEUE_WAKEUP 0x20000002 38 | #define TEE_RPC_WAIT 0x30000000 39 | 40 | /* Parameters for TEE_RPC_WAIT_MUTEX above */ 41 | #define TEE_MUTEX_WAIT_SLEEP 0 42 | #define TEE_MUTEX_WAIT_WAKEUP 1 43 | #define TEE_MUTEX_WAIT_DELETE 2 44 | 45 | #define TEE_RPC_FREE_TA 0x10000009 46 | #define TEE_RPC_FS 0x10000010 47 | #define TEE_RPC_LOAD_TA2 0x10000012 48 | 49 | #include 50 | 51 | /** 52 | * struct tee_rpc_bf - Contains definition of the tee com buffer 53 | * @state: Buffer state 54 | * @data: Command data 55 | */ 56 | struct tee_rpc_bf { 57 | uint32_t state; 58 | uint8_t data[TEE_RPC_DATA_SIZE]; 59 | }; 60 | 61 | struct tee_rpc_alloc { 62 | uint32_t size; /* size of block */ 63 | void *data; /* pointer to data */ 64 | void *shm; /* pointer to an opaque data, being shm structure */ 65 | }; 66 | 67 | struct tee_rpc_free { 68 | void *shm; /* pointer to an opaque data, being shm structure */ 69 | }; 70 | 71 | struct tee_rpc_cmd { 72 | union { 73 | void *buffer; 74 | uint64_t padding_buf; 75 | }; 76 | uint32_t size; 77 | uint32_t type; 78 | int fd; 79 | int reserved; 80 | }; 81 | 82 | struct tee_rpc_invoke { 83 | uint32_t cmd; 84 | uint32_t res; 85 | uint32_t nbr_bf; 86 | uint32_t reserved; 87 | struct tee_rpc_cmd cmds[TEE_RPC_BUFFER_NUMBER]; 88 | }; 89 | 90 | struct tee_rpc { 91 | struct tee_rpc_invoke commToUser; 92 | struct tee_rpc_invoke commFromUser; 93 | struct semaphore datatouser; 94 | struct semaphore datafromuser; 95 | struct mutex thrd_mutex; /* Block the thread to wait for supp answer */ 96 | struct mutex outsync; /* Out sync mutex */ 97 | struct mutex insync; /* In sync mutex */ 98 | struct mutex reqsync; /* Request sync mutex */ 99 | atomic_t used; 100 | }; 101 | 102 | enum teec_rpc_result { 103 | TEEC_RPC_OK, 104 | TEEC_RPC_FAIL 105 | }; 106 | 107 | struct tee; 108 | 109 | int tee_supp_init(struct tee *tee); 110 | void tee_supp_deinit(struct tee *tee); 111 | 112 | enum teec_rpc_result tee_supp_cmd(struct tee *tee, 113 | uint32_t id, void *data, size_t datalen); 114 | 115 | ssize_t tee_supp_read(struct file *filp, char __user *buffer, 116 | size_t length, loff_t *offset); 117 | 118 | ssize_t tee_supp_write(struct file *filp, const char __user *buffer, 119 | size_t length, loff_t *offset); 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /core/tee_sysfs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "tee_core_priv.h" 20 | 21 | static ssize_t dump_show(struct device *device, 22 | struct device_attribute *attr, char *buf) 23 | { 24 | struct tee *tee = dev_get_drvdata(device); 25 | int len; 26 | char *tmp_buf; 27 | 28 | tmp_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); 29 | if (!tmp_buf) { 30 | printk(KERN_ALERT "%s : Unable to get buf memory\n", __func__); 31 | return -ENOMEM; 32 | } 33 | 34 | len = tee_context_dump(tee, tmp_buf, PAGE_SIZE - 128); 35 | 36 | if (len > 0) 37 | len = snprintf(buf, PAGE_SIZE, "%s", tmp_buf); 38 | kfree(tmp_buf); 39 | 40 | return len; 41 | } 42 | 43 | static ssize_t stat_show(struct device *device, 44 | struct device_attribute *attr, char *buf) 45 | { 46 | struct tee *tee = dev_get_drvdata(device); 47 | 48 | return snprintf(buf, PAGE_SIZE, "%d/%d %d/%d %d/%d %d/%d\n", 49 | atomic_read(&tee->refcount), 50 | tee->max_refcount, 51 | tee->stats[TEE_STATS_CONTEXT_IDX].count, 52 | tee->stats[TEE_STATS_CONTEXT_IDX].max, 53 | tee->stats[TEE_STATS_SESSION_IDX].count, 54 | tee->stats[TEE_STATS_SESSION_IDX].max, 55 | tee->stats[TEE_STATS_SHM_IDX].count, 56 | tee->stats[TEE_STATS_SHM_IDX].max); 57 | } 58 | 59 | static ssize_t info_show(struct device *device, 60 | struct device_attribute *attr, char *buf) 61 | { 62 | struct tee *tee = dev_get_drvdata(device); 63 | 64 | return snprintf(buf, PAGE_SIZE, "%s iminor=%d dev=\"%s\" state=%d\n", 65 | dev_name(tee->dev), tee->miscdev.minor, 66 | dev_name(tee->miscdev.this_device), tee->state); 67 | } 68 | 69 | static ssize_t name_show(struct device *device, 70 | struct device_attribute *attr, char *buf) 71 | { 72 | struct tee *tee = dev_get_drvdata(device); 73 | 74 | return snprintf(buf, PAGE_SIZE, "%s\n", tee->name); 75 | } 76 | 77 | static ssize_t type_show(struct device *device, 78 | struct device_attribute *attr, char *buf) 79 | { 80 | struct tee *tee = dev_get_drvdata(device); 81 | 82 | return snprintf(buf, PAGE_SIZE, "%s\n", tee->ops->type); 83 | } 84 | 85 | static ssize_t refcount_show(struct device *device, 86 | struct device_attribute *attr, char *buf) 87 | { 88 | struct tee *tee = dev_get_drvdata(device); 89 | 90 | return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&tee->refcount)); 91 | } 92 | 93 | static ssize_t conf_show(struct device *device, 94 | struct device_attribute *attr, char *buf) 95 | { 96 | struct tee *tee = dev_get_drvdata(device); 97 | 98 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", tee->conf); 99 | } 100 | 101 | static ssize_t test_show(struct device *device, 102 | struct device_attribute *attr, char *buf) 103 | { 104 | struct tee *tee = dev_get_drvdata(device); 105 | 106 | return snprintf(buf, PAGE_SIZE, "%08X\n", tee->test); 107 | } 108 | 109 | static ssize_t test_store(struct device *device, 110 | struct device_attribute *attr, const char *buf, 111 | size_t count) 112 | { 113 | struct tee *tee = dev_get_drvdata(device); 114 | unsigned long val; 115 | int status; 116 | 117 | status = kstrtoul(buf, 0, &val); 118 | if (status) 119 | return status; 120 | 121 | if ((tee->conf & TEE_CONF_TEST_MODE) == TEE_CONF_TEST_MODE) 122 | tee->test = val; 123 | 124 | return count; 125 | } 126 | 127 | /* 128 | * A state-to-string lookup table, for exposing a human readable state 129 | * via sysfs. Always keep in sync with enum tee_state 130 | */ 131 | static const char *const tee_state_string[] = { 132 | "offline", 133 | "online", 134 | "suspended", 135 | "running", 136 | "crashed", 137 | "invalid", 138 | }; 139 | 140 | static ssize_t tee_show_state(struct device *device, 141 | struct device_attribute *attr, char *buf) 142 | { 143 | struct tee *tee = dev_get_drvdata(device); 144 | 145 | int state = tee->state > TEE_LAST ? TEE_LAST : tee->state; 146 | 147 | return snprintf(buf, PAGE_SIZE, "%s (%d)\n", tee_state_string[state], 148 | tee->state); 149 | } 150 | 151 | /* 152 | * In the following, 0660 is (S_IWUGO | S_IRUGO) 153 | */ 154 | static struct device_attribute device_attrs[] = { 155 | __ATTR_RO(dump), 156 | __ATTR_RO(stat), 157 | __ATTR_RO(info), 158 | __ATTR(test, (0660), test_show, test_store), 159 | __ATTR(state, S_IRUGO, tee_show_state, NULL), 160 | __ATTR(name, S_IRUGO, name_show, NULL), 161 | __ATTR(refcount, S_IRUGO, refcount_show, NULL), 162 | __ATTR(type, S_IRUGO, type_show, NULL), 163 | __ATTR(conf, S_IRUGO, conf_show, NULL), 164 | }; 165 | 166 | void tee_init_sysfs(struct tee *tee) 167 | { 168 | int i, error = 0; 169 | 170 | if (!tee) 171 | return; 172 | 173 | if (dev_get_drvdata(tee->miscdev.this_device) != tee) { 174 | dev_err(_DEV(tee), "drvdata is not valid\n"); 175 | return; 176 | } 177 | 178 | for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { 179 | error = 180 | device_create_file(tee->miscdev.this_device, 181 | &device_attrs[i]); 182 | if (error) 183 | break; 184 | } 185 | 186 | if (error) { 187 | while (--i >= 0) 188 | device_remove_file(tee->miscdev.this_device, 189 | &device_attrs[i]); 190 | } 191 | /* location /sys/class/// -> 192 | * /sys/class/misc/teelx00/info */ 193 | } 194 | 195 | void tee_cleanup_sysfs(struct tee *tee) 196 | { 197 | int i; 198 | 199 | if (!tee) 200 | return; 201 | 202 | for (i = 0; i < ARRAY_SIZE(device_attrs); i++) 203 | device_remove_file(tee->miscdev.this_device, &device_attrs[i]); 204 | } 205 | -------------------------------------------------------------------------------- /core/tee_sysfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #ifndef __TEE_SYSFS_H__ 14 | #define __TEE_SYSFS_H__ 15 | 16 | struct tee; 17 | 18 | void tee_init_sysfs(struct tee *tee); 19 | void tee_cleanup_sysfs(struct tee *tee); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /core/tee_wait_queue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Linaro Limited 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #include 14 | #include 15 | #include 16 | #include "tee_wait_queue.h" 17 | 18 | struct tee_wait_queue { 19 | struct list_head link; 20 | struct completion comp; 21 | u32 key; 22 | }; 23 | 24 | void tee_wait_queue_init(struct tee_wait_queue_private *priv) 25 | { 26 | mutex_init(&priv->mu); 27 | INIT_LIST_HEAD(&priv->db); 28 | } 29 | EXPORT_SYMBOL(tee_wait_queue_init); 30 | 31 | void tee_wait_queue_exit(struct tee_wait_queue_private *priv) 32 | { 33 | mutex_destroy(&priv->mu); 34 | } 35 | EXPORT_SYMBOL(tee_wait_queue_exit); 36 | 37 | static struct tee_wait_queue *tee_wait_queue_get(struct device *dev, 38 | struct tee_wait_queue_private *priv, u32 key) 39 | { 40 | struct tee_wait_queue *w; 41 | 42 | mutex_lock(&priv->mu); 43 | 44 | list_for_each_entry(w, &priv->db, link) 45 | if (w->key == key) 46 | goto out; 47 | 48 | w = kmalloc(sizeof(struct tee_wait_queue), GFP_KERNEL); 49 | if (!w) 50 | goto out; 51 | 52 | init_completion(&w->comp); 53 | w->key = key; 54 | list_add_tail(&w->link, &priv->db); 55 | out: 56 | mutex_unlock(&priv->mu); 57 | return w; 58 | } 59 | 60 | void tee_wait_queue_sleep(struct device *dev, 61 | struct tee_wait_queue_private *priv, u32 key) 62 | { 63 | struct tee_wait_queue *w = tee_wait_queue_get(dev, priv, key); 64 | 65 | if (!w) 66 | return; 67 | 68 | wait_for_completion(&w->comp); 69 | mutex_lock(&priv->mu); 70 | list_del(&w->link); 71 | mutex_unlock(&priv->mu); 72 | kfree(w); 73 | } 74 | EXPORT_SYMBOL(tee_wait_queue_sleep); 75 | 76 | void tee_wait_queue_wakeup(struct device *dev, 77 | struct tee_wait_queue_private *priv, u32 key) 78 | { 79 | struct tee_wait_queue *w = tee_wait_queue_get(dev, priv, key); 80 | 81 | if (!w) 82 | return; 83 | 84 | complete(&w->comp); 85 | } 86 | EXPORT_SYMBOL(tee_wait_queue_wakeup); 87 | -------------------------------------------------------------------------------- /core/tee_wait_queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Linaro Limited 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #ifndef TEE_WAIT_QUEUE_H 14 | #define TEE_WAIT_QUEUE_H 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | struct tee_wait_queue_private { 21 | struct mutex mu; 22 | struct list_head db; 23 | }; 24 | 25 | void tee_wait_queue_init(struct tee_wait_queue_private *priv); 26 | void tee_wait_queue_exit(struct tee_wait_queue_private *priv); 27 | void tee_wait_queue_sleep(struct device *dev, 28 | struct tee_wait_queue_private *priv, u32 key); 29 | void tee_wait_queue_wakeup(struct device *dev, 30 | struct tee_wait_queue_private *priv, u32 key); 31 | 32 | #endif /*TEE_WAIT_QUEUE_H*/ 33 | -------------------------------------------------------------------------------- /fdts/fvp-foundation-gicv2-psci.dts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. 9 | * 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * Neither the name of the ARM nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without specific 16 | * prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | /dts-v1/; 32 | 33 | /memreserve/ 0x80000000 0x00010000; 34 | 35 | / { 36 | }; 37 | 38 | / { 39 | model = "FVP Foundation"; 40 | compatible = "arm,fvp-base", "arm,vexpress"; 41 | interrupt-parent = <&gic>; 42 | #address-cells = <2>; 43 | #size-cells = <2>; 44 | 45 | chosen { }; 46 | 47 | aliases { 48 | serial0 = &v2m_serial0; 49 | serial1 = &v2m_serial1; 50 | serial2 = &v2m_serial2; 51 | serial3 = &v2m_serial3; 52 | }; 53 | 54 | psci { 55 | compatible = "arm,psci"; 56 | method = "smc"; 57 | cpu_suspend = <0xc4000001>; 58 | cpu_off = <0x84000002>; 59 | cpu_on = <0xc4000003>; 60 | }; 61 | 62 | cpus { 63 | #address-cells = <2>; 64 | #size-cells = <0>; 65 | 66 | cpu@0 { 67 | device_type = "cpu"; 68 | compatible = "arm,armv8"; 69 | reg = <0x0 0x0>; 70 | enable-method = "psci"; 71 | }; 72 | cpu@1 { 73 | device_type = "cpu"; 74 | compatible = "arm,armv8"; 75 | reg = <0x0 0x1>; 76 | enable-method = "psci"; 77 | }; 78 | cpu@2 { 79 | device_type = "cpu"; 80 | compatible = "arm,armv8"; 81 | reg = <0x0 0x2>; 82 | enable-method = "psci"; 83 | }; 84 | cpu@3 { 85 | device_type = "cpu"; 86 | compatible = "arm,armv8"; 87 | reg = <0x0 0x3>; 88 | enable-method = "psci"; 89 | }; 90 | }; 91 | 92 | memory@80000000 { 93 | device_type = "memory"; 94 | reg = <0x00000000 0x80000000 0 0x7F000000>, 95 | <0x00000008 0x80000000 0 0x80000000>; 96 | }; 97 | 98 | reserved-memory { 99 | #address-cells = <2>; 100 | #size-cells = <2>; 101 | ranges; 102 | 103 | optee@0x83000000 { 104 | reg = <0x00000000 0x83000000 0 0x01000000>; 105 | }; 106 | }; 107 | 108 | gic: interrupt-controller@2f000000 { 109 | compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; 110 | #interrupt-cells = <3>; 111 | #address-cells = <0>; 112 | interrupt-controller; 113 | reg = <0x0 0x2f000000 0 0x10000>, 114 | <0x0 0x2c000000 0 0x2000>, 115 | <0x0 0x2c010000 0 0x2000>, 116 | <0x0 0x2c02F000 0 0x2000>; 117 | interrupts = <1 9 0xf04>; 118 | }; 119 | 120 | timer { 121 | compatible = "arm,armv8-timer"; 122 | interrupts = <1 13 0xff01>, 123 | <1 14 0xff01>, 124 | <1 11 0xff01>, 125 | <1 10 0xff01>; 126 | clock-frequency = <100000000>; 127 | }; 128 | 129 | timer@2a810000 { 130 | compatible = "arm,armv7-timer-mem"; 131 | reg = <0x0 0x2a810000 0x0 0x10000>; 132 | clock-frequency = <100000000>; 133 | #address-cells = <2>; 134 | #size-cells = <2>; 135 | ranges; 136 | frame@2a830000 { 137 | frame-number = <1>; 138 | interrupts = <0 26 4>; 139 | reg = <0x0 0x2a830000 0x0 0x10000>; 140 | }; 141 | }; 142 | 143 | pmu { 144 | compatible = "arm,armv8-pmuv3"; 145 | interrupts = <0 60 4>, 146 | <0 61 4>, 147 | <0 62 4>, 148 | <0 63 4>; 149 | }; 150 | 151 | smb { 152 | compatible = "simple-bus"; 153 | 154 | #address-cells = <2>; 155 | #size-cells = <1>; 156 | ranges = <0 0 0 0x08000000 0x04000000>, 157 | <1 0 0 0x14000000 0x04000000>, 158 | <2 0 0 0x18000000 0x04000000>, 159 | <3 0 0 0x1c000000 0x04000000>, 160 | <4 0 0 0x0c000000 0x04000000>, 161 | <5 0 0 0x10000000 0x04000000>; 162 | 163 | #interrupt-cells = <1>; 164 | interrupt-map-mask = <0 0 63>; 165 | interrupt-map = <0 0 0 &gic 0 0 4>, 166 | <0 0 1 &gic 0 1 4>, 167 | <0 0 2 &gic 0 2 4>, 168 | <0 0 3 &gic 0 3 4>, 169 | <0 0 4 &gic 0 4 4>, 170 | <0 0 5 &gic 0 5 4>, 171 | <0 0 6 &gic 0 6 4>, 172 | <0 0 7 &gic 0 7 4>, 173 | <0 0 8 &gic 0 8 4>, 174 | <0 0 9 &gic 0 9 4>, 175 | <0 0 10 &gic 0 10 4>, 176 | <0 0 11 &gic 0 11 4>, 177 | <0 0 12 &gic 0 12 4>, 178 | <0 0 13 &gic 0 13 4>, 179 | <0 0 14 &gic 0 14 4>, 180 | <0 0 15 &gic 0 15 4>, 181 | <0 0 16 &gic 0 16 4>, 182 | <0 0 17 &gic 0 17 4>, 183 | <0 0 18 &gic 0 18 4>, 184 | <0 0 19 &gic 0 19 4>, 185 | <0 0 20 &gic 0 20 4>, 186 | <0 0 21 &gic 0 21 4>, 187 | <0 0 22 &gic 0 22 4>, 188 | <0 0 23 &gic 0 23 4>, 189 | <0 0 24 &gic 0 24 4>, 190 | <0 0 25 &gic 0 25 4>, 191 | <0 0 26 &gic 0 26 4>, 192 | <0 0 27 &gic 0 27 4>, 193 | <0 0 28 &gic 0 28 4>, 194 | <0 0 29 &gic 0 29 4>, 195 | <0 0 30 &gic 0 30 4>, 196 | <0 0 31 &gic 0 31 4>, 197 | <0 0 32 &gic 0 32 4>, 198 | <0 0 33 &gic 0 33 4>, 199 | <0 0 34 &gic 0 34 4>, 200 | <0 0 35 &gic 0 35 4>, 201 | <0 0 36 &gic 0 36 4>, 202 | <0 0 37 &gic 0 37 4>, 203 | <0 0 38 &gic 0 38 4>, 204 | <0 0 39 &gic 0 39 4>, 205 | <0 0 40 &gic 0 40 4>, 206 | <0 0 41 &gic 0 41 4>, 207 | <0 0 42 &gic 0 42 4>; 208 | 209 | /include/ "fvp-foundation-motherboard.dtsi" 210 | }; 211 | }; 212 | -------------------------------------------------------------------------------- /fdts/fvp-foundation-motherboard.dtsi: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. 9 | * 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 14 | * Neither the name of the ARM nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without specific 16 | * prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | motherboard { 32 | arm,v2m-memory-map = "rs1"; 33 | compatible = "arm,vexpress,v2m-p1", "simple-bus"; 34 | #address-cells = <2>; /* SMB chipselect number and offset */ 35 | #size-cells = <1>; 36 | #interrupt-cells = <1>; 37 | ranges; 38 | 39 | ethernet@2,02000000 { 40 | compatible = "smsc,lan91c111"; 41 | reg = <2 0x02000000 0x10000>; 42 | interrupts = <15>; 43 | }; 44 | 45 | v2m_clk24mhz: clk24mhz { 46 | compatible = "fixed-clock"; 47 | #clock-cells = <0>; 48 | clock-frequency = <24000000>; 49 | clock-output-names = "v2m:clk24mhz"; 50 | }; 51 | 52 | v2m_refclk1mhz: refclk1mhz { 53 | compatible = "fixed-clock"; 54 | #clock-cells = <0>; 55 | clock-frequency = <1000000>; 56 | clock-output-names = "v2m:refclk1mhz"; 57 | }; 58 | 59 | v2m_refclk32khz: refclk32khz { 60 | compatible = "fixed-clock"; 61 | #clock-cells = <0>; 62 | clock-frequency = <32768>; 63 | clock-output-names = "v2m:refclk32khz"; 64 | }; 65 | 66 | iofpga@3,00000000 { 67 | compatible = "arm,amba-bus", "simple-bus"; 68 | #address-cells = <1>; 69 | #size-cells = <1>; 70 | ranges = <0 3 0 0x200000>; 71 | 72 | v2m_sysreg: sysreg@010000 { 73 | compatible = "arm,vexpress-sysreg"; 74 | reg = <0x010000 0x1000>; 75 | gpio-controller; 76 | #gpio-cells = <2>; 77 | }; 78 | 79 | v2m_sysctl: sysctl@020000 { 80 | compatible = "arm,sp810", "arm,primecell"; 81 | reg = <0x020000 0x1000>; 82 | clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>; 83 | clock-names = "refclk", "timclk", "apb_pclk"; 84 | #clock-cells = <1>; 85 | clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3"; 86 | }; 87 | 88 | v2m_serial0: uart@090000 { 89 | compatible = "arm,pl011", "arm,primecell"; 90 | reg = <0x090000 0x1000>; 91 | interrupts = <5>; 92 | clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; 93 | clock-names = "uartclk", "apb_pclk"; 94 | }; 95 | 96 | v2m_serial1: uart@0a0000 { 97 | compatible = "arm,pl011", "arm,primecell"; 98 | reg = <0x0a0000 0x1000>; 99 | interrupts = <6>; 100 | clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; 101 | clock-names = "uartclk", "apb_pclk"; 102 | }; 103 | 104 | v2m_serial2: uart@0b0000 { 105 | compatible = "arm,pl011", "arm,primecell"; 106 | reg = <0x0b0000 0x1000>; 107 | interrupts = <7>; 108 | clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; 109 | clock-names = "uartclk", "apb_pclk"; 110 | }; 111 | 112 | v2m_serial3: uart@0c0000 { 113 | compatible = "arm,pl011", "arm,primecell"; 114 | reg = <0x0c0000 0x1000>; 115 | interrupts = <8>; 116 | clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; 117 | clock-names = "uartclk", "apb_pclk"; 118 | }; 119 | 120 | wdt@0f0000 { 121 | compatible = "arm,sp805", "arm,primecell"; 122 | reg = <0x0f0000 0x1000>; 123 | interrupts = <0>; 124 | clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>; 125 | clock-names = "wdogclk", "apb_pclk"; 126 | }; 127 | 128 | v2m_timer01: timer@110000 { 129 | compatible = "arm,sp804", "arm,primecell"; 130 | reg = <0x110000 0x1000>; 131 | interrupts = <2>; 132 | clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>; 133 | clock-names = "timclken1", "timclken2", "apb_pclk"; 134 | }; 135 | 136 | v2m_timer23: timer@120000 { 137 | compatible = "arm,sp804", "arm,primecell"; 138 | reg = <0x120000 0x1000>; 139 | interrupts = <3>; 140 | clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>; 141 | clock-names = "timclken1", "timclken2", "apb_pclk"; 142 | }; 143 | 144 | rtc@170000 { 145 | compatible = "arm,pl031", "arm,primecell"; 146 | reg = <0x170000 0x1000>; 147 | interrupts = <4>; 148 | clocks = <&v2m_clk24mhz>; 149 | clock-names = "apb_pclk"; 150 | }; 151 | 152 | virtio_block@0130000 { 153 | compatible = "virtio,mmio"; 154 | reg = <0x130000 0x1000>; 155 | interrupts = <0x2a>; 156 | }; 157 | }; 158 | 159 | v2m_fixed_3v3: fixedregulator@0 { 160 | compatible = "regulator-fixed"; 161 | regulator-name = "3V3"; 162 | regulator-min-microvolt = <3300000>; 163 | regulator-max-microvolt = <3300000>; 164 | regulator-always-on; 165 | }; 166 | 167 | 168 | mcc { 169 | compatible = "arm,vexpress,config-bus", "simple-bus"; 170 | arm,vexpress,config-bridge = <&v2m_sysreg>; 171 | 172 | reset@0 { 173 | compatible = "arm,vexpress-reset"; 174 | arm,vexpress-sysreg,func = <5 0>; 175 | }; 176 | 177 | muxfpga@0 { 178 | compatible = "arm,vexpress-muxfpga"; 179 | arm,vexpress-sysreg,func = <7 0>; 180 | }; 181 | 182 | shutdown@0 { 183 | compatible = "arm,vexpress-shutdown"; 184 | arm,vexpress-sysreg,func = <8 0>; 185 | }; 186 | 187 | reboot@0 { 188 | compatible = "arm,vexpress-reboot"; 189 | arm,vexpress-sysreg,func = <9 0>; 190 | }; 191 | 192 | dvimode@0 { 193 | compatible = "arm,vexpress-dvimode"; 194 | arm,vexpress-sysreg,func = <11 0>; 195 | }; 196 | }; 197 | }; 198 | -------------------------------------------------------------------------------- /fdts/readme.txt: -------------------------------------------------------------------------------- 1 | These files is a temporary workaround until the driver has switched 2 | to use CMA to allocate shared memory. 3 | -------------------------------------------------------------------------------- /include/arm_common/optee_msg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Linaro Limited 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #ifndef _OPTEE_MSG_H 28 | #define _OPTEE_MSG_H 29 | 30 | #include 31 | 32 | /* 33 | * This file defines the OP-TEE message protocol used to communicate 34 | * with an instance of OP-TEE running in secure world. 35 | * 36 | * This file is divided into three sections. 37 | * 1. Formatting of messages. 38 | * 2. Requests from normal world 39 | * 3. Requests from secure world, Remote Procedure Call (RPC), handled by 40 | * tee-supplicant. 41 | */ 42 | 43 | /***************************************************************************** 44 | * Part 1 - formatting of messages 45 | *****************************************************************************/ 46 | 47 | #define OPTEE_MSG_ATTR_TYPE_NONE 0x0 48 | #define OPTEE_MSG_ATTR_TYPE_VALUE_INPUT 0x1 49 | #define OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT 0x2 50 | #define OPTEE_MSG_ATTR_TYPE_VALUE_INOUT 0x3 51 | #define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT 0x5 52 | #define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT 0x6 53 | #define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT 0x7 54 | #define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT 0x9 55 | #define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT 0xa 56 | #define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT 0xb 57 | 58 | #define OPTEE_MSG_ATTR_TYPE_MASK 0xff 59 | 60 | /* 61 | * Meta parameter to be absorbed by the Secure OS and not passed 62 | * to the Trusted Application. 63 | * 64 | * Currently only used with OPTEE_MSG_CMD_OPEN_SESSION. 65 | */ 66 | #define OPTEE_MSG_ATTR_META (1 << 8) 67 | 68 | /* 69 | * The temporary shared memory object is not physically contiguous and this 70 | * temp memref is followed by another fragment until the last temp memref 71 | * that doesn't have this bit set. 72 | */ 73 | #define OPTEE_MSG_ATTR_FRAGMENT (1 << 9) 74 | 75 | /* 76 | * Memory attributes for caching passed with temp memrefs. The actual value 77 | * used is defined outside the message protocol with the exception of 78 | * OPTEE_MSG_ATTR_CACHE_PREDEFINED which means the attributes already 79 | * defined for the memory range should be used. If optee_smc.h is used as 80 | * bearer of this protocol OPTEE_SMC_SHM_* is used for values. 81 | */ 82 | #define OPTEE_MSG_ATTR_CACHE_SHIFT 16 83 | #define OPTEE_MSG_ATTR_CACHE_MASK 0x7 84 | #define OPTEE_MSG_ATTR_CACHE_PREDEFINED 0 85 | 86 | /* 87 | * Same values as TEE_LOGIN_* from TEE Internal API 88 | */ 89 | #define OPTEE_MSG_LOGIN_PUBLIC 0x00000000 90 | #define OPTEE_MSG_LOGIN_USER 0x00000001 91 | #define OPTEE_MSG_LOGIN_GROUP 0x00000002 92 | #define OPTEE_MSG_LOGIN_APPLICATION 0x00000004 93 | #define OPTEE_MSG_LOGIN_APPLICATION_USER 0x00000005 94 | #define OPTEE_MSG_LOGIN_APPLICATION_GROUP 0x00000006 95 | 96 | /** 97 | * struct optee_msg_param_tmem - temporary memory reference 98 | * @buf_ptr: Address of the buffer 99 | * @size: Size of the buffer 100 | * @shm_ref: Temporary shared memory reference, pointer to a struct tee_shm 101 | * 102 | * Secure and normal world communicates pointers as physical address 103 | * instead of the virtual address. This is because secure and normal world 104 | * have completely independent memory mapping. Normal world can even have a 105 | * hypervisor which need to translate the guest physical address (AKA IPA 106 | * in ARM documentation) to a real physical address before passing the 107 | * structure to secure world. 108 | */ 109 | struct optee_msg_param_tmem { 110 | u64 buf_ptr; 111 | u64 size; 112 | u64 shm_ref; 113 | }; 114 | 115 | /** 116 | * struct optee_msg_param_rmem - registered memory reference 117 | * @offs: Offset into shared memory reference 118 | * @size: Size of the buffer 119 | * @shm_ref: Shared memory reference, pointer to a struct tee_shm 120 | */ 121 | struct optee_msg_param_rmem { 122 | u64 offs; 123 | u64 size; 124 | u64 shm_ref; 125 | }; 126 | 127 | /** 128 | * struct optee_msg_param_value - values 129 | * @a: first value 130 | * @b: second value 131 | * @c: third value 132 | */ 133 | struct optee_msg_param_value { 134 | u64 a; 135 | u64 b; 136 | u64 c; 137 | }; 138 | 139 | /** 140 | * struct optee_msg_param - parameter 141 | * @attr: attributes 142 | * @memref: a memory reference 143 | * @value: a value 144 | * 145 | * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in 146 | * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value, 147 | * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates tmem and 148 | * OPTEE_MSG_ATTR_TYPE_RMEM_* indicates rmem. 149 | * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used. 150 | */ 151 | struct optee_msg_param { 152 | u64 attr; 153 | union { 154 | struct optee_msg_param_tmem tmem; 155 | struct optee_msg_param_rmem rmem; 156 | struct optee_msg_param_value value; 157 | } u; 158 | }; 159 | 160 | /** 161 | * struct optee_msg_arg - call argument 162 | * @cmd: Command, one of OPTEE_MSG_CMD_* or OPTEE_MSG_RPC_CMD_* 163 | * @func: Trusted Application function, specific to the Trusted Application, 164 | * used if cmd == OPTEE_MSG_CMD_INVOKE_COMMAND 165 | * @session: In parameter for all OPTEE_MSG_CMD_* except 166 | * OPTEE_MSG_CMD_OPEN_SESSION where it's an output parameter instead 167 | * @cancel_id: Cancellation id, a unique value to identify this request 168 | * @ret: return value 169 | * @ret_origin: origin of the return value 170 | * @num_params: number of parameters supplied to the OS Command 171 | * @params: the parameters supplied to the OS Command 172 | * 173 | * All normal calls to Trusted OS uses this struct. If cmd requires further 174 | * information than what these fields hold it can be passed as a parameter 175 | * tagged as meta (setting the OPTEE_MSG_ATTR_META bit in corresponding 176 | * attrs field). All parameters tagged as meta have to come first. 177 | * 178 | * Temp memref parameters can be fragmented if supported by the Trusted OS 179 | * (when optee_smc.h is bearer of this protocol this is indicated with 180 | * OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM). If a logical memref parameter is 181 | * fragmented then all but the last fragment have the 182 | * OPTEE_MSG_ATTR_FRAGMENT bit set in attrs. Even if a memref is fragmented 183 | * it will still be presented as a single logical memref to the Trusted 184 | * Application. 185 | */ 186 | struct optee_msg_arg { 187 | u32 cmd; 188 | u32 func; 189 | u32 session; 190 | u32 cancel_id; 191 | u32 pad; 192 | u32 ret; 193 | u32 ret_origin; 194 | u32 num_params; 195 | 196 | /* 197 | * this struct is 8 byte aligned since the 'struct optee_msg_param' 198 | * which follows requires 8 byte alignment. 199 | * 200 | * Commented out element used to visualize the layout dynamic part 201 | * of the struct. This field is not available at all if 202 | * num_params == 0. 203 | * 204 | * params is accessed through the macro OPTEE_MSG_GET_PARAMS 205 | * 206 | * struct optee_msg_param params[num_params]; 207 | */ 208 | } __aligned(8); 209 | 210 | /** 211 | * OPTEE_MSG_GET_PARAMS - return pointer to struct optee_msg_param * 212 | * 213 | * @x: Pointer to a struct optee_msg_arg 214 | * 215 | * Returns a pointer to the params[] inside a struct optee_msg_arg. 216 | */ 217 | #define OPTEE_MSG_GET_PARAMS(x) \ 218 | (struct optee_msg_param *)(((struct optee_msg_arg *)(x)) + 1) 219 | 220 | /** 221 | * OPTEE_MSG_GET_ARG_SIZE - return size of struct optee_msg_arg 222 | * 223 | * @num_params: Number of parameters embedded in the struct optee_msg_arg 224 | * 225 | * Returns the size of the struct optee_msg_arg together with the number 226 | * of embedded parameters. 227 | */ 228 | #define OPTEE_MSG_GET_ARG_SIZE(num_params) \ 229 | (sizeof(struct optee_msg_arg) + \ 230 | sizeof(struct optee_msg_param) * (num_params)) 231 | 232 | /***************************************************************************** 233 | * Part 2 - requests from normal world 234 | *****************************************************************************/ 235 | 236 | /* 237 | * Return the following UID if using API specified in this file without 238 | * further extensions: 239 | * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b. 240 | * Represented in 4 32-bit words in OPTEE_MSG_UID_0, OPTEE_MSG_UID_1, 241 | * OPTEE_MSG_UID_2, OPTEE_MSG_UID_3. 242 | */ 243 | #define OPTEE_MSG_UID_0 0x384fb3e0 244 | #define OPTEE_MSG_UID_1 0xe7f811e3 245 | #define OPTEE_MSG_UID_2 0xaf630002 246 | #define OPTEE_MSG_UID_3 0xa5d5c51b 247 | #define OPTEE_MSG_FUNCID_CALLS_UID 0xFF01 248 | 249 | /* 250 | * Returns 2.0 if using API specified in this file without further 251 | * extensions. Represented in 2 32-bit words in OPTEE_MSG_REVISION_MAJOR 252 | * and OPTEE_MSG_REVISION_MINOR 253 | */ 254 | #define OPTEE_MSG_REVISION_MAJOR 2 255 | #define OPTEE_MSG_REVISION_MINOR 0 256 | #define OPTEE_MSG_FUNCID_CALLS_REVISION 0xFF03 257 | 258 | /* 259 | * Get UUID of Trusted OS. 260 | * 261 | * Used by non-secure world to figure out which Trusted OS is installed. 262 | * Note that returned UUID is the UUID of the Trusted OS, not of the API. 263 | * 264 | * Returns UUID in 4 32-bit words in the same way as 265 | * OPTEE_MSG_FUNCID_CALLS_UID described above. 266 | */ 267 | #define OPTEE_MSG_OS_OPTEE_UUID_0 0x486178e0 268 | #define OPTEE_MSG_OS_OPTEE_UUID_1 0xe7f811e3 269 | #define OPTEE_MSG_OS_OPTEE_UUID_2 0xbc5e0002 270 | #define OPTEE_MSG_OS_OPTEE_UUID_3 0xa5d5c51b 271 | #define OPTEE_MSG_FUNCID_GET_OS_UUID 0x0000 272 | 273 | /* 274 | * Get revision of Trusted OS. 275 | * 276 | * Used by non-secure world to figure out which version of the Trusted OS 277 | * is installed. Note that the returned revision is the revision of the 278 | * Trusted OS, not of the API. 279 | * 280 | * Returns revision in 2 32-bit words in the same way as 281 | * OPTEE_MSG_CALLS_REVISION described above. 282 | */ 283 | #define OPTEE_MSG_FUNCID_GET_OS_REVISION 0x0001 284 | 285 | /* 286 | * Do a secure call with struct optee_msg_arg as argument 287 | * The OPTEE_MSG_CMD_* below defines what goes in struct optee_msg_arg::cmd 288 | * 289 | * OPTEE_MSG_CMD_OPEN_SESSION opens a session to a Trusted Application. 290 | * The first two parameters are tagged as meta, holding two value 291 | * parameters to pass the following information: 292 | * param[0].u.value.a-b uuid of Trusted Application 293 | * param[1].u.value.a-b uuid of Client 294 | * param[1].u.value.c Login class of client OPTEE_MSG_LOGIN_* 295 | * 296 | * OPTEE_MSG_CMD_INVOKE_COMMAND invokes a command a previously opened 297 | * session to a Trusted Application. struct optee_msg_arg::func is Trusted 298 | * Application function, specific to the Trusted Application. 299 | * 300 | * OPTEE_MSG_CMD_CLOSE_SESSION closes a previously opened session to 301 | * Trusted Application. 302 | * 303 | * OPTEE_MSG_CMD_CANCEL cancels a currently invoked command. 304 | * 305 | * OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The 306 | * information is passed as: 307 | * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_TMEM_INPUT 308 | * [| OPTEE_MSG_ATTR_FRAGMENT] 309 | * [in] param[0].u.tmem.buf_ptr physical address (of first fragment) 310 | * [in] param[0].u.tmem.size size (of first fragment) 311 | * [in] param[0].u.tmem.shm_ref holds shared memory reference 312 | * ... 313 | * The shared memory can optionally be fragmented, temp memrefs can follow 314 | * each other with all but the last with the OPTEE_MSG_ATTR_FRAGMENT bit set. 315 | * 316 | * OPTEE_MSG_CMD_UNREGISTER_SHM unregisteres a previously registered shared 317 | * memory reference. The information is passed as: 318 | * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_RMEM_INPUT 319 | * [in] param[0].u.rmem.shm_ref holds shared memory reference 320 | * [in] param[0].u.rmem.offs 0 321 | * [in] param[0].u.rmem.size 0 322 | */ 323 | #define OPTEE_MSG_CMD_OPEN_SESSION 0 324 | #define OPTEE_MSG_CMD_INVOKE_COMMAND 1 325 | #define OPTEE_MSG_CMD_CLOSE_SESSION 2 326 | #define OPTEE_MSG_CMD_CANCEL 3 327 | #define OPTEE_MSG_CMD_REGISTER_SHM 4 328 | #define OPTEE_MSG_CMD_UNREGISTER_SHM 5 329 | #define OPTEE_MSG_FUNCID_CALL_WITH_ARG 0x0004 330 | 331 | /***************************************************************************** 332 | * Part 3 - Requests from secure world, RPC 333 | *****************************************************************************/ 334 | 335 | /* 336 | * All RPC is done with a struct optee_msg_arg as bearer of information, 337 | * struct optee_msg_arg::arg holds values defined by OPTEE_MSG_RPC_CMD_* below 338 | * 339 | * RPC communication with tee-supplicant is reversed compared to normal 340 | * client communication desribed above. The supplicant receives requests 341 | * and sends responses. 342 | */ 343 | 344 | /* 345 | * Load a TA into memory, defined in tee-supplicant 346 | */ 347 | #define OPTEE_MSG_RPC_CMD_LOAD_TA 0 348 | 349 | /* 350 | * Replay Protected Memory Block access, defined in tee-supplicant 351 | */ 352 | #define OPTEE_MSG_RPC_CMD_RPMB 1 353 | 354 | /* 355 | * File system access, defined in tee-supplicant 356 | */ 357 | #define OPTEE_MSG_RPC_CMD_FS 2 358 | 359 | /* 360 | * Get time 361 | * 362 | * Returns number of seconds and nano seconds since the Epoch, 363 | * 1970-01-01 00:00:00 +0000 (UTC). 364 | * 365 | * [out] param[0].u.value.a Number of seconds 366 | * [out] param[0].u.value.b Number of nano seconds. 367 | */ 368 | #define OPTEE_MSG_RPC_CMD_GET_TIME 3 369 | 370 | /* 371 | * Wait queue primitive, helper for secure world to implement a wait queue 372 | * 373 | * Waiting on a key 374 | * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP 375 | * [in] param[0].u.value.b wait key 376 | * 377 | * Waking up a key 378 | * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP 379 | * [in] param[0].u.value.b wakeup key 380 | */ 381 | #define OPTEE_MSG_RPC_CMD_WAIT_QUEUE 4 382 | #define OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP 0 383 | #define OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP 1 384 | 385 | /* 386 | * Suspend execution 387 | * 388 | * [in] param[0].value .a number of milliseconds to suspend 389 | */ 390 | #define OPTEE_MSG_RPC_CMD_SUSPEND 5 391 | 392 | /* 393 | * Allocate a piece of shared memory 394 | * 395 | * Shared memory can optionally be fragmented, to support that additional 396 | * spare param entries are allocated to make room for eventual fragments. 397 | * The spare param entries has .attr = OPTEE_MSG_ATTR_TYPE_NONE when 398 | * unused. All returned temp memrefs except the last should have the 399 | * OPTEE_MSG_ATTR_FRAGMENT bit set in the attr field. 400 | * 401 | * [in] param[0].u.value.a type of memory one of 402 | * OPTEE_MSG_RPC_SHM_TYPE_* below 403 | * [in] param[0].u.value.b requested size 404 | * [in] param[0].u.value.c required alignment 405 | * 406 | * [out] param[0].u.tmem.buf_ptr physical address (of first fragment) 407 | * [out] param[0].u.tmem.size size (of first fragment) 408 | * [out] param[0].u.tmem.shm_ref shared memory reference 409 | * ... 410 | * [out] param[n].u.tmem.buf_ptr physical address 411 | * [out] param[n].u.tmem.size size 412 | * [out] param[n].u.tmem.shm_ref shared memory reference (same value 413 | * as in param[n-1].u.tmem.shm_ref) 414 | */ 415 | #define OPTEE_MSG_RPC_CMD_SHM_ALLOC 6 416 | /* Memory that can be shared with a non-secure user space application */ 417 | #define OPTEE_MSG_RPC_SHM_TYPE_APPL 0 418 | /* Memory only shared with non-secure kernel */ 419 | #define OPTEE_MSG_RPC_SHM_TYPE_KERNEL 1 420 | 421 | #endif /* _OPTEE_MSG_H */ 422 | -------------------------------------------------------------------------------- /include/arm_common/optee_smc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Linaro Limited 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #ifndef OPTEE_SMC_H 28 | #define OPTEE_SMC_H 29 | 30 | /* 31 | * This file is exported by OP-TEE and is in kept in sync between secure 32 | * world and normal world kernel driver. We're following ARM SMC Calling 33 | * Convention as specified in 34 | * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html 35 | * 36 | * This file depends on optee_msg.h being included to expand the SMC id 37 | * macros below. 38 | */ 39 | 40 | #define OPTEE_SMC_32 0 41 | #define OPTEE_SMC_64 0x40000000 42 | #define OPTEE_SMC_FAST_CALL 0x80000000 43 | #define OPTEE_SMC_STD_CALL 0 44 | 45 | #define OPTEE_SMC_OWNER_MASK 0x3F 46 | #define OPTEE_SMC_OWNER_SHIFT 24 47 | 48 | #define OPTEE_SMC_FUNC_MASK 0xFFFF 49 | 50 | #define OPTEE_SMC_IS_FAST_CALL(smc_val) ((smc_val) & OPTEE_SMC_FAST_CALL) 51 | #define OPTEE_SMC_IS_64(smc_val) ((smc_val) & OPTEE_SMC_64) 52 | #define OPTEE_SMC_FUNC_NUM(smc_val) ((smc_val) & OPTEE_SMC_FUNC_MASK) 53 | #define OPTEE_SMC_OWNER_NUM(smc_val) \ 54 | (((smc_val) >> OPTEE_SMC_OWNER_SHIFT) & OPTEE_SMC_OWNER_MASK) 55 | 56 | #define OPTEE_SMC_CALL_VAL(type, calling_convention, owner, func_num) \ 57 | ((type) | (calling_convention) | \ 58 | (((owner) & OPTEE_SMC_OWNER_MASK) << \ 59 | OPTEE_SMC_OWNER_SHIFT) |\ 60 | ((func_num) & OPTEE_SMC_FUNC_MASK)) 61 | 62 | #define OPTEE_SMC_STD_CALL_VAL(func_num) \ 63 | OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_STD_CALL, \ 64 | OPTEE_SMC_OWNER_TRUSTED_OS, (func_num)) 65 | #define OPTEE_SMC_FAST_CALL_VAL(func_num) \ 66 | OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ 67 | OPTEE_SMC_OWNER_TRUSTED_OS, (func_num)) 68 | 69 | #define OPTEE_SMC_OWNER_ARCH 0 70 | #define OPTEE_SMC_OWNER_CPU 1 71 | #define OPTEE_SMC_OWNER_SIP 2 72 | #define OPTEE_SMC_OWNER_OEM 3 73 | #define OPTEE_SMC_OWNER_STANDARD 4 74 | #define OPTEE_SMC_OWNER_TRUSTED_APP 48 75 | #define OPTEE_SMC_OWNER_TRUSTED_OS 50 76 | 77 | #define OPTEE_SMC_OWNER_TRUSTED_OS_OPTEED 62 78 | #define OPTEE_SMC_OWNER_TRUSTED_OS_API 63 79 | 80 | /* 81 | * Function specified by SMC Calling convention. 82 | */ 83 | #define OPTEE_SMC_FUNCID_CALLS_COUNT 0xFF00 84 | #define OPTEE_SMC_CALLS_COUNT \ 85 | OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ 86 | OPTEE_SMC_OWNER_TRUSTED_OS_API, \ 87 | OPTEE_SMC_FUNCID_CALLS_COUNT) 88 | 89 | /* 90 | * Normal cached memory (write-back), shareable for SMP systems and not 91 | * shareable for UP systems. 92 | */ 93 | #define OPTEE_SMC_SHM_CACHED 1 94 | 95 | /* 96 | * a0..a7 is used as register names in the descriptions below, on arm32 97 | * that translates to r0..r7 and on arm64 to w0..w7. In both cases it's 98 | * 32-bit registers. 99 | */ 100 | 101 | /* 102 | * Function specified by SMC Calling convention 103 | * 104 | * Return the following UID if using API specified in this file 105 | * without further extensions: 106 | * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b. 107 | * see also OPTEE_MSG_UID_* in optee_msg.h 108 | */ 109 | #define OPTEE_SMC_FUNCID_CALLS_UID OPTEE_MSG_FUNCID_CALLS_UID 110 | #define OPTEE_SMC_CALLS_UID \ 111 | OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ 112 | OPTEE_SMC_OWNER_TRUSTED_OS_API, \ 113 | OPTEE_SMC_FUNCID_CALLS_UID) 114 | 115 | /* 116 | * Function specified by SMC Calling convention 117 | * 118 | * Returns 2.0 if using API specified in this file without further extensions. 119 | * see also OPTEE_MSG_REVISION_* in optee_msg.h 120 | */ 121 | #define OPTEE_SMC_FUNCID_CALLS_REVISION OPTEE_MSG_FUNCID_CALLS_REVISION 122 | #define OPTEE_SMC_CALLS_REVISION \ 123 | OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ 124 | OPTEE_SMC_OWNER_TRUSTED_OS_API, \ 125 | OPTEE_SMC_FUNCID_CALLS_REVISION) 126 | 127 | /* 128 | * Get UUID of Trusted OS. 129 | * 130 | * Used by non-secure world to figure out which Trusted OS is installed. 131 | * Note that returned UUID is the UUID of the Trusted OS, not of the API. 132 | * 133 | * Returns UUID in a0-4 in the same way as OPTEE_SMC_CALLS_UID 134 | * described above. 135 | */ 136 | #define OPTEE_SMC_FUNCID_GET_OS_UUID OPTEE_MSG_FUNCID_GET_OS_UUID 137 | #define OPTEE_SMC_CALL_GET_OS_UUID \ 138 | OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_UUID) 139 | 140 | /* 141 | * Get revision of Trusted OS. 142 | * 143 | * Used by non-secure world to figure out which version of the Trusted OS 144 | * is installed. Note that the returned revision is the revision of the 145 | * Trusted OS, not of the API. 146 | * 147 | * Returns revision in a0-1 in the same way as OPTEE_SMC_CALLS_REVISION 148 | * described above. 149 | */ 150 | #define OPTEE_SMC_FUNCID_GET_OS_REVISION OPTEE_MSG_FUNCID_GET_OS_REVISION 151 | #define OPTEE_SMC_CALL_GET_OS_REVISION \ 152 | OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_REVISION) 153 | 154 | /* 155 | * Call with struct optee_msg_arg as argument 156 | * 157 | * Call register usage: 158 | * a0 SMC Function ID, OPTEE_SMC*CALL_WITH_ARG 159 | * a1 Upper 32 bits of a 64-bit physical pointer to a struct optee_msg_arg 160 | * a2 Lower 32 bits of a 64-bit physical pointer to a struct optee_msg_arg 161 | * a3 Cache settings, not used if physical pointer is in a predefined shared 162 | * memory area else per OPTEE_SMC_SHM_* 163 | * a4-6 Not used 164 | * a7 Hypervisor Client ID register 165 | * 166 | * Normal return register usage: 167 | * a0 Return value, OPTEE_SMC_RETURN_* 168 | * a1-3 Not used 169 | * a4-7 Preserved 170 | * 171 | * OPTEE_SMC_RETURN_ETHREAD_LIMIT return register usage: 172 | * a0 Return value, OPTEE_SMC_RETURN_ETHREAD_LIMIT 173 | * a1-3 Preserved 174 | * a4-7 Preserved 175 | * 176 | * RPC return register usage: 177 | * a0 Return value, OPTEE_SMC_RETURN_IS_RPC(val) 178 | * a1-2 RPC parameters 179 | * a3-7 Resume information, must be preserved 180 | * 181 | * Possible return values: 182 | * OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this 183 | * function. 184 | * OPTEE_SMC_RETURN_OK Call completed, result updated in 185 | * the previously supplied struct 186 | * optee_msg_arg. 187 | * OPTEE_SMC_RETURN_ETHREAD_LIMIT Number of Trusted OS threads exceeded, 188 | * try again later. 189 | * OPTEE_SMC_RETURN_EBADADDR Bad physical pointer to struct 190 | * optee_msg_arg. 191 | * OPTEE_SMC_RETURN_EBADCMD Bad/unknown cmd in struct optee_msg_arg 192 | * OPTEE_SMC_RETURN_IS_RPC() Call suspended by RPC call to normal 193 | * world. 194 | */ 195 | #define OPTEE_SMC_FUNCID_CALL_WITH_ARG OPTEE_MSG_FUNCID_CALL_WITH_ARG 196 | #define OPTEE_SMC_CALL_WITH_ARG \ 197 | OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_ARG) 198 | 199 | /* 200 | * Get Shared Memory Config 201 | * 202 | * Returns the Secure/Non-secure shared memory config. 203 | * 204 | * Call register usage: 205 | * a0 SMC Function ID, OPTEE_SMC_GET_SHM_CONFIG 206 | * a1-6 Not used 207 | * a7 Hypervisor Client ID register 208 | * 209 | * Have config return register usage: 210 | * a0 OPTEE_SMC_RETURN_OK 211 | * a1 Physical address of start of SHM 212 | * a2 Size of of SHM 213 | * a3 Cache settings of memory, as defined by the 214 | * OPTEE_SMC_SHM_* values above 215 | * a4-7 Preserved 216 | * 217 | * Not available register usage: 218 | * a0 OPTEE_SMC_RETURN_ENOTAVAIL 219 | * a1-3 Not used 220 | * a4-7 Preserved 221 | */ 222 | #define OPTEE_SMC_FUNCID_GET_SHM_CONFIG 7 223 | #define OPTEE_SMC_GET_SHM_CONFIG \ 224 | OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_SHM_CONFIG) 225 | 226 | /* 227 | * Configures L2CC mutex 228 | * 229 | * Disables, enables usage of L2CC mutex. Returns or sets physical address 230 | * of L2CC mutex. 231 | * 232 | * Call register usage: 233 | * a0 SMC Function ID, OPTEE_SMC_L2CC_MUTEX 234 | * a1 OPTEE_SMC_L2CC_MUTEX_GET_ADDR Get physical address of mutex 235 | * OPTEE_SMC_L2CC_MUTEX_SET_ADDR Set physical address of mutex 236 | * OPTEE_SMC_L2CC_MUTEX_ENABLE Enable usage of mutex 237 | * OPTEE_SMC_L2CC_MUTEX_DISABLE Disable usage of mutex 238 | * a2 if a1 == OPTEE_SMC_L2CC_MUTEX_SET_ADDR, upper 32bit of a 64bit 239 | * physical address of mutex 240 | * a3 if a1 == OPTEE_SMC_L2CC_MUTEX_SET_ADDR, lower 32bit of a 64bit 241 | * physical address of mutex 242 | * a3-6 Not used 243 | * a7 Hypervisor Client ID register 244 | * 245 | * Have config return register usage: 246 | * a0 OPTEE_SMC_RETURN_OK 247 | * a1 Preserved 248 | * a2 if a1 == OPTEE_SMC_L2CC_MUTEX_GET_ADDR, upper 32bit of a 64bit 249 | * physical address of mutex 250 | * a3 if a1 == OPTEE_SMC_L2CC_MUTEX_GET_ADDR, lower 32bit of a 64bit 251 | * physical address of mutex 252 | * a3-7 Preserved 253 | * 254 | * Error return register usage: 255 | * a0 OPTEE_SMC_RETURN_ENOTAVAIL Physical address not available 256 | * OPTEE_SMC_RETURN_EBADADDR Bad supplied physical address 257 | * OPTEE_SMC_RETURN_EBADCMD Unsupported value in a1 258 | * a1-7 Preserved 259 | */ 260 | #define OPTEE_SMC_L2CC_MUTEX_GET_ADDR 0 261 | #define OPTEE_SMC_L2CC_MUTEX_SET_ADDR 1 262 | #define OPTEE_SMC_L2CC_MUTEX_ENABLE 2 263 | #define OPTEE_SMC_L2CC_MUTEX_DISABLE 3 264 | #define OPTEE_SMC_FUNCID_L2CC_MUTEX 8 265 | #define OPTEE_SMC_L2CC_MUTEX \ 266 | OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_L2CC_MUTEX) 267 | 268 | /* 269 | * Exchanges capabilities between normal world and secure world 270 | * 271 | * Call register usage: 272 | * a0 SMC Function ID, OPTEE_SMC_EXCHANGE_CAPABILITIES 273 | * a1 bitfield of normal world capabilities OPTEE_SMC_NSEC_CAP_* 274 | * a2-6 Not used 275 | * a7 Hypervisor Client ID register 276 | * 277 | * Normal return register usage: 278 | * a0 OPTEE_SMC_RETURN_OK 279 | * a1 bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_* 280 | * a2-7 Preserved 281 | * 282 | * Error return register usage: 283 | * a0 OPTEE_SMC_RETURN_ENOTAVAIL, can't use the capabilities from normal world 284 | * a1 bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_* 285 | * a2-7 Preserved 286 | */ 287 | /* Normal world works as a uniprocessor system */ 288 | #define OPTEE_SMC_NSEC_CAP_UNIPROCESSOR (1 << 0) 289 | /* Secure world has reserved shared memory for normal world to use */ 290 | #define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM (1 << 0) 291 | /* Secure world can communicate via previously unregistered shared memory */ 292 | #define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM (1 << 1) 293 | #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9 294 | #define OPTEE_SMC_EXCHANGE_CAPABILITIES \ 295 | OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES) 296 | 297 | /* 298 | * Disable and empties cache of shared memory objects 299 | * 300 | * Secure world can cache frequently used shared memory objects, for 301 | * example objects used as RPC arguments. When secure world is idle this 302 | * function returns one shared memory reference to free. To disable the 303 | * cache and free all cached objects this function has to be called until 304 | * it returns OPTEE_SMC_RETURN_ENOTAVAIL. 305 | * 306 | * Call register usage: 307 | * a0 SMC Function ID, OPTEE_SMC_DISABLE_SHM_CACHE 308 | * a1-6 Not used 309 | * a7 Hypervisor Client ID register 310 | * 311 | * Normal return register usage: 312 | * a0 OPTEE_SMC_RETURN_OK 313 | * a1 Upper 32 bits of a 64-bit Shared memory cookie 314 | * a2 Lower 32 bits of a 64-bit Shared memory cookie 315 | * a3-7 Preserved 316 | * 317 | * Cache empty return register usage: 318 | * a0 OPTEE_SMC_RETURN_ENOTAVAIL 319 | * a1-7 Preserved 320 | * 321 | * Not idle return register usage: 322 | * a0 OPTEE_SMC_RETURN_EBUSY 323 | * a1-7 Preserved 324 | */ 325 | #define OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE 10 326 | #define OPTEE_SMC_DISABLE_SHM_CACHE \ 327 | OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE) 328 | 329 | 330 | /* 331 | * Enable cache of shared memory objects 332 | * 333 | * Secure world can cache frequently used shared memory objects, for 334 | * example objects used as RPC arguments. When secure world is idle this 335 | * function returns OPTEE_SMC_RETURN_OK and the cache is enabled. If 336 | * secure world isn't idle OPTEE_SMC_RETURN_EBUSY is returned. 337 | * 338 | * Call register usage: 339 | * a0 SMC Function ID, OPTEE_SMC_ENABLE_SHM_CACHE 340 | * a1-6 Not used 341 | * a7 Hypervisor Client ID register 342 | * 343 | * Normal return register usage: 344 | * a0 OPTEE_SMC_RETURN_OK 345 | * a1-7 Preserved 346 | * 347 | * Not idle return register usage: 348 | * a0 OPTEE_SMC_RETURN_EBUSY 349 | * a1-7 Preserved 350 | */ 351 | #define OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE 11 352 | #define OPTEE_SMC_ENABLE_SHM_CACHE \ 353 | OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE) 354 | 355 | /* 356 | * Resume from RPC (for example after processing an IRQ) 357 | * 358 | * Call register usage: 359 | * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC 360 | * a1-3 Value of a1-3 when OPTEE_SMC_CALL_WITH_ARG returned 361 | * OPTEE_SMC_RETURN_RPC in a0 362 | * 363 | * Return register usage is the same as for OPTEE_SMC_*CALL_WITH_ARG above. 364 | * 365 | * Possible return values 366 | * OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this 367 | * function. 368 | * OPTEE_SMC_RETURN_OK Original call completed, result 369 | * updated in the previously supplied. 370 | * struct optee_msg_arg 371 | * OPTEE_SMC_RETURN_RPC Call suspended by RPC call to normal 372 | * world. 373 | * OPTEE_SMC_RETURN_ERESUME Resume failed, the opaque resume 374 | * information was corrupt. 375 | */ 376 | #define OPTEE_SMC_FUNCID_RETURN_FROM_RPC 3 377 | #define OPTEE_SMC_CALL_RETURN_FROM_RPC \ 378 | OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_RETURN_FROM_RPC) 379 | 380 | #define OPTEE_SMC_RETURN_RPC_PREFIX_MASK 0xFFFF0000 381 | #define OPTEE_SMC_RETURN_RPC_PREFIX 0xFFFF0000 382 | #define OPTEE_SMC_RETURN_RPC_FUNC_MASK 0x0000FFFF 383 | 384 | #define OPTEE_SMC_RETURN_GET_RPC_FUNC(ret) \ 385 | ((ret) & OPTEE_SMC_RETURN_RPC_FUNC_MASK) 386 | 387 | #define OPTEE_SMC_RPC_VAL(func) ((func) | OPTEE_SMC_RETURN_RPC_PREFIX) 388 | 389 | /* 390 | * Allocate memory for RPC parameter passing. The memory is used to hold a 391 | * struct optee_msg_arg. 392 | * 393 | * "Call" register usage: 394 | * a0 This value, OPTEE_SMC_RETURN_RPC_ALLOC 395 | * a1 Size in bytes of required argument memory 396 | * a2 Not used 397 | * a3 Resume information, must be preserved 398 | * a4-5 Not used 399 | * a6-7 Resume information, must be preserved 400 | * 401 | * "Return" register usage: 402 | * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC. 403 | * a1 Upper 32 bits of 64-bit physical pointer to allocated 404 | * memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't 405 | * be allocated. 406 | * a2 Lower 32 bits of 64-bit physical pointer to allocated 407 | * memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't 408 | * be allocated 409 | * a3 Preserved 410 | * a4 Upper 32 bits of 64-bit Shared memory cookie used when freeing 411 | * the memory or doing an RPC 412 | * a5 Lower 32 bits of 64-bit Shared memory cookie used when freeing 413 | * the memory or doing an RPC 414 | * a6-7 Preserved 415 | */ 416 | #define OPTEE_SMC_RPC_FUNC_ALLOC 0 417 | #define OPTEE_SMC_RETURN_RPC_ALLOC \ 418 | OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_ALLOC) 419 | 420 | /* 421 | * Free memory previously allocated by OPTEE_SMC_RETURN_RPC_ALLOC 422 | * 423 | * "Call" register usage: 424 | * a0 This value, OPTEE_SMC_RETURN_RPC_FREE_ARG 425 | * a1 Upper 32 bits of 64-bit shared memory cookie belonging to this 426 | * argument memory 427 | * a2 Lower 32 bits of 64-bit shared memory cookie belonging to this 428 | * argument memory 429 | * a3-7 Resume information, must be preserved 430 | * 431 | * "Return" register usage: 432 | * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC. 433 | * a1-2 Not used 434 | * a3-7 Preserved 435 | */ 436 | #define OPTEE_SMC_RPC_FUNC_FREE 2 437 | #define OPTEE_SMC_RETURN_RPC_FREE \ 438 | OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FREE) 439 | 440 | /* 441 | * Deliver an IRQ in normal world. 442 | * 443 | * "Call" register usage: 444 | * a0 OPTEE_SMC_RETURN_RPC_IRQ 445 | * a1-7 Resume information, must be preserved 446 | * 447 | * "Return" register usage: 448 | * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC. 449 | * a1-7 Preserved 450 | */ 451 | #define OPTEE_SMC_RPC_FUNC_IRQ 4 452 | #define OPTEE_SMC_RETURN_RPC_IRQ \ 453 | OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_IRQ) 454 | 455 | /* 456 | * Do an RPC request. The supplied struct optee_msg_arg tells which 457 | * request to do and the parameters for the request. The following fields 458 | * are used (the rest are unused): 459 | * - cmd the Request ID 460 | * - ret return value of the request, filled in by normal world 461 | * - num_params number of parameters for the request 462 | * - params the parameters 463 | * - param_attrs attributes of the parameters 464 | * 465 | * "Call" register usage: 466 | * a0 OPTEE_SMC_RETURN_RPC_CMD 467 | * a1 Upper 32 bits of a 64-bit Shared memory cookie holding a 468 | * struct optee_msg_arg, must be preserved, only the data should 469 | * be updated 470 | * a2 Lower 32 bits of a 64-bit Shared memory cookie holding a 471 | * struct optee_msg_arg, must be preserved, only the data should 472 | * be updated 473 | * a3-7 Resume information, must be preserved 474 | * 475 | * "Return" register usage: 476 | * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC. 477 | * a1-2 Not used 478 | * a3-7 Preserved 479 | */ 480 | #define OPTEE_SMC_RPC_FUNC_CMD 5 481 | #define OPTEE_SMC_RETURN_RPC_CMD \ 482 | OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_CMD) 483 | 484 | /* Returned in a0 */ 485 | #define OPTEE_SMC_RETURN_UNKNOWN_FUNCTION 0xFFFFFFFF 486 | 487 | /* Returned in a0 only from Trusted OS functions */ 488 | #define OPTEE_SMC_RETURN_OK 0x0 489 | #define OPTEE_SMC_RETURN_ETHREAD_LIMIT 0x1 490 | #define OPTEE_SMC_RETURN_EBUSY 0x2 491 | #define OPTEE_SMC_RETURN_ERESUME 0x3 492 | #define OPTEE_SMC_RETURN_EBADADDR 0x4 493 | #define OPTEE_SMC_RETURN_EBADCMD 0x5 494 | #define OPTEE_SMC_RETURN_ENOMEM 0x6 495 | #define OPTEE_SMC_RETURN_ENOTAVAIL 0x7 496 | #define OPTEE_SMC_RETURN_IS_RPC(ret) \ 497 | (((ret) != OPTEE_SMC_RETURN_UNKNOWN_FUNCTION) && \ 498 | ((((ret) & OPTEE_SMC_RETURN_RPC_PREFIX_MASK) == \ 499 | OPTEE_SMC_RETURN_RPC_PREFIX))) 500 | 501 | #endif /* OPTEE_SMC_H */ 502 | -------------------------------------------------------------------------------- /include/linux/tee_core.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #ifndef __TEE_CORE_DRV_H__ 14 | #define __TEE_CORE_DRV_H__ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include 29 | 30 | struct tee_cmd_io; 31 | struct tee_shm_io; 32 | struct tee_rpc; 33 | 34 | enum tee_state { 35 | TEE_OFFLINE = 0, 36 | TEE_ONLINE = 1, 37 | TEE_SUSPENDED = 2, 38 | TEE_RUNNING = 3, 39 | TEE_CRASHED = 4, 40 | TEE_LAST = 5, 41 | }; 42 | 43 | #define TEE_CONF_TEST_MODE 0x01000000 44 | #define TEE_CONF_FW_NOT_CAPABLE 0x00000001 45 | 46 | struct tee_stats_entry { 47 | int count; 48 | int max; 49 | }; 50 | 51 | #define TEE_STATS_CONTEXT_IDX 0 52 | #define TEE_STATS_SESSION_IDX 1 53 | #define TEE_STATS_SHM_IDX 2 54 | 55 | #define TEE_MAX_TEE_DEV_NAME (64) 56 | struct tee { 57 | struct klist_node node; 58 | char name[TEE_MAX_TEE_DEV_NAME]; 59 | int id; 60 | void *priv; 61 | const struct tee_ops *ops; 62 | struct device *dev; 63 | struct miscdevice miscdev; 64 | struct tee_rpc *rpc; 65 | struct dentry *dbg_dir; 66 | atomic_t refcount; 67 | int max_refcount; 68 | struct tee_stats_entry stats[3]; 69 | struct list_head list_ctx; 70 | struct list_head list_rpc_shm; 71 | struct mutex lock; 72 | unsigned int state; 73 | uint32_t shm_flags; /* supported flags for shm allocation */ 74 | uint32_t conf; 75 | uint32_t test; 76 | }; 77 | 78 | #define _DEV(tee) (tee->miscdev.this_device) 79 | 80 | #define TEE_MAX_CLIENT_NAME (128) 81 | 82 | /** 83 | * struct tee_context - internal structure to store a TEE context. 84 | * 85 | * @tee: tee attached to the tee_context 86 | * @usr_client: flag to known if the client is user side client 87 | * @entry: list of tee_context 88 | * @list_sess: list of tee_session that denotes all tee_session attached 89 | * @list_shm: list of tee_shm that denotes all tee_shm attached 90 | * @refcount: number of objects which reference it (including itself) 91 | */ 92 | struct tee_context { 93 | struct tee *tee; 94 | char name[TEE_MAX_CLIENT_NAME]; 95 | int tgid; 96 | int usr_client; 97 | struct list_head entry; 98 | struct list_head list_sess; 99 | struct list_head list_shm; 100 | struct kref refcount; 101 | }; 102 | 103 | /** 104 | * struct tee_session - internal structure to store a TEE session. 105 | * 106 | * @entry: list of tee_context 107 | * @ctx: tee_context attached to the tee_session 108 | * @sessid: session ID returned by the secure world 109 | * @priv: exporter specific private data for this buffer object 110 | */ 111 | struct tee_session { 112 | struct list_head entry; 113 | struct tee_context *ctx; 114 | uint32_t sessid; 115 | void *priv; 116 | }; 117 | 118 | struct tee_shm_dma_buf { 119 | struct dma_buf_attachment *attach; 120 | struct sg_table *sgt; 121 | bool tee_allocated; 122 | }; 123 | 124 | /** 125 | * struct tee_shm - internal structure to store a shm object. 126 | * 127 | * @ctx: tee_context attached to the buffer. 128 | * @tee: tee attached to the buffer. 129 | * @dev: device attached to the buffer. 130 | * @size_req: requested size for the buffer 131 | * @size_alloc: effective size of the buffer 132 | * @kaddr: kernel address if mapped kernel side 133 | * @paddr: physical address 134 | * @flags: flags which denote the type of the buffer 135 | * @entry: list of tee_shm 136 | */ 137 | struct tee_shm { 138 | struct list_head entry; 139 | struct tee_context *ctx; 140 | struct tee *tee; 141 | struct device *dev; 142 | size_t size_req; 143 | size_t size_alloc; 144 | uint32_t flags; 145 | void *kaddr; 146 | dma_addr_t paddr; 147 | struct sg_table sgt; 148 | struct tee_shm_dma_buf *sdb; 149 | }; 150 | 151 | #define TEE_SHM_MAPPED 0x01000000 152 | #define TEE_SHM_TEMP 0x02000000 153 | #define TEE_SHM_FROM_RPC 0x04000000 154 | #define TEE_SHM_REGISTERED 0x08000000 155 | #define TEE_SHM_MEMREF 0x10000000 156 | #define TEE_SHM_CACHED 0x20000000 157 | 158 | #define TEE_SHM_DRV_PRIV_MASK 0xFF000000 159 | 160 | struct tee_data { 161 | uint32_t type; 162 | uint32_t type_original; 163 | TEEC_SharedMemory c_shm[TEEC_CONFIG_PAYLOAD_REF_COUNT]; 164 | union { 165 | struct tee_shm *shm; 166 | TEEC_Value value; 167 | } params[TEEC_CONFIG_PAYLOAD_REF_COUNT]; 168 | }; 169 | 170 | struct tee_cmd { 171 | TEEC_Result err; 172 | uint32_t origin; 173 | uint32_t cmd; 174 | struct tee_shm *uuid; 175 | struct tee_shm *ta; 176 | struct tee_data param; 177 | }; 178 | 179 | struct tee_shm *tee_shm_alloc_from_rpc(struct tee *tee, size_t size); 180 | void tee_shm_free_from_rpc(struct tee_shm *); 181 | 182 | int tee_core_add(struct tee *tee); 183 | int tee_core_del(struct tee *tee); 184 | 185 | struct tee *tee_core_alloc(struct device *dev, char *name, int id, 186 | const struct tee_ops *ops, size_t len); 187 | int tee_core_free(struct tee *tee); 188 | 189 | struct tee_ops { 190 | struct module *owner; 191 | const char *type; 192 | 193 | int (*start)(struct tee *tee); 194 | int (*stop)(struct tee *tee); 195 | int (*open)(struct tee_session *sess, struct tee_cmd *cmd); 196 | int (*close)(struct tee_session *sess); 197 | int (*invoke)(struct tee_session *sess, struct tee_cmd *cmd); 198 | int (*cancel)(struct tee_session *sess, struct tee_cmd *cmd); 199 | struct tee_shm *(*alloc)(struct tee *tee, size_t size, 200 | uint32_t flags); 201 | void (*free)(struct tee_shm *shm); 202 | int (*shm_inc_ref)(struct tee_shm *shm); 203 | }; 204 | 205 | #endif /* __TEE_CORE_DRV_H__ */ 206 | -------------------------------------------------------------------------------- /include/linux/tee_ioc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #ifndef _TEE_IOC_H 14 | #define _TEE_IOC_H 15 | 16 | #include 17 | 18 | #ifndef __KERNEL__ 19 | #define __user 20 | #endif 21 | 22 | /** 23 | * struct tee_cmd_io - The command sent to an open tee device. 24 | * @err: Error code (as in Global Platform TEE Client API spec) 25 | * @origin: Origin for the error code (also from spec). 26 | * @cmd: The command to be executed in the trusted application. 27 | * @uuid: The uuid for the trusted application. 28 | * @data: The trusted application or memory block. 29 | * @data_size: The size of the trusted application or memory block. 30 | * @op: The cmd payload operation for the trusted application. 31 | * 32 | * This structure is mainly used in the Linux kernel for communication 33 | * with the user space. 34 | */ 35 | struct tee_cmd_io { 36 | TEEC_Result err; 37 | uint32_t origin; 38 | uint32_t cmd; 39 | int fd_sess; 40 | /* 41 | * Here fd_sess is 32-bit variable. Since TEEC_Result also is defined as 42 | * "uint32_t", this structure is aligned. 43 | */ 44 | union { 45 | TEEC_UUID __user *uuid; 46 | uint64_t padding_uuid; 47 | }; 48 | union { 49 | void __user *data; 50 | uint64_t padding_data; 51 | }; 52 | union { 53 | TEEC_Operation __user *op; 54 | uint64_t padding_op; 55 | }; 56 | uint32_t data_size; 57 | int32_t reserved; 58 | }; 59 | 60 | struct tee_shm_io { 61 | union { 62 | void __user *buffer; 63 | uint64_t padding_buf; 64 | }; 65 | uint32_t size; 66 | uint32_t flags; 67 | /* 68 | * Here fd_shm is 32-bit. To be compliant with the convention of file 69 | * descriptor definition, fd_shm is defined as "int" type other 70 | * than "int32_t". Even though using "int32_t" is more obvious to 71 | * indicate that we intend to keep this structure aligned. 72 | */ 73 | int fd_shm; 74 | uint32_t registered; 75 | }; 76 | 77 | #define TEE_OPEN_SESSION_IOC _IOWR('t', 161, struct tee_cmd_io) 78 | #define TEE_INVOKE_COMMAND_IOC _IOWR('t', 163, struct tee_cmd_io) 79 | #define TEE_REQUEST_CANCELLATION_IOC _IOWR('t', 164, struct tee_cmd_io) 80 | #define TEE_ALLOC_SHM_IOC _IOWR('t', 165, struct tee_shm_io) 81 | #define TEE_GET_FD_FOR_RPC_SHM_IOC _IOWR('t', 167, struct tee_shm_io) 82 | 83 | #endif /* _TEE_IOC_H */ 84 | -------------------------------------------------------------------------------- /include/linux/tee_kernel_api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, STMicroelectronics International N.V. 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License Version 2 as 6 | * published by the Free Software Foundation. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | #ifndef _TEE_KERNEL_API_H 14 | #define _TEE_KERNEL_API_H 15 | 16 | #include 17 | 18 | /** 19 | * struct TEEC_Context - Represents a connection between a client application 20 | * and a TEE. 21 | */ 22 | /*typedef struct { 23 | char devname[256]; 24 | } TEEC_Context;*/ 25 | 26 | /** 27 | * struct TEEC_Session - Represents a connection between a client application 28 | * and a trusted application. 29 | */ 30 | /*typedef struct { 31 | void *session; 32 | } TEEC_Session;*/ 33 | 34 | /** 35 | * TEEC_InitializeContext() - Initializes a context holding connection 36 | * information on the specific TEE, designated by the name string. 37 | 38 | * @param name A zero-terminated string identifying the TEE to connect to. 39 | * If name is set to NULL, the default TEE is connected to. NULL 40 | * is the only supported value in this version of the API 41 | * implementation. 42 | * 43 | * @param context The context structure which is to be initialized. 44 | * 45 | * @return TEEC_SUCCESS The initialization was successful. 46 | * @return TEEC_Result Something failed. 47 | */ 48 | TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *context); 49 | 50 | /** 51 | * TEEC_FinalizeContext() - Destroys a context holding connection information 52 | * on the specific TEE. 53 | * 54 | * This function destroys an initialized TEE context, closing the connection 55 | * between the client application and the TEE. This function must only be 56 | * called when all sessions related to this TEE context have been closed and 57 | * all shared memory blocks have been released. 58 | * 59 | * @param context The context to be destroyed. 60 | */ 61 | void TEEC_FinalizeContext(TEEC_Context *context); 62 | 63 | /** 64 | * TEEC_OpenSession() - Opens a new session with the specified trusted 65 | * application. 66 | * 67 | * @param context The initialized TEE context structure in which 68 | * scope to open the session. 69 | * @param session The session to initialize. 70 | * @param destination A structure identifying the trusted application 71 | * with which to open a session. 72 | * 73 | * @param connectionMethod The connection method to use. 74 | * @param connectionData Any data necessary to connect with the chosen 75 | * connection method. Not supported, should be set to 76 | * NULL. 77 | * @param operation An operation structure to use in the session. May 78 | * be set to NULL to signify no operation structure 79 | * needed. 80 | * 81 | * @param returnOrigin A parameter which will hold the error origin if 82 | * this function returns any value other than 83 | * TEEC_SUCCESS. 84 | * 85 | * @return TEEC_SUCCESS OpenSession successfully opened a new session. 86 | * @return TEEC_Result Something failed. 87 | * 88 | */ 89 | TEEC_Result TEEC_OpenSession(TEEC_Context *context, 90 | TEEC_Session *session, 91 | const TEEC_UUID *destination, 92 | uint32_t connectionMethod, 93 | const void *connectionData, 94 | TEEC_Operation *operation, 95 | uint32_t *returnOrigin); 96 | 97 | /** 98 | * TEEC_CloseSession() - Closes the session which has been opened with the 99 | * specific trusted application. 100 | * 101 | * @param session The opened session to close. 102 | */ 103 | void TEEC_CloseSession(TEEC_Session *session); 104 | 105 | /** 106 | * TEEC_InvokeCommand() - Executes a command in the specified trusted 107 | * application. 108 | * 109 | * @param session A handle to an open connection to the trusted 110 | * application. 111 | * @param commandID Identifier of the command in the trusted application 112 | * to invoke. 113 | * @param operation An operation structure to use in the invoke command. 114 | * May be set to NULL to signify no operation structure 115 | * needed. 116 | * @param returnOrigin A parameter which will hold the error origin if this 117 | * function returns any value other than TEEC_SUCCESS. 118 | * 119 | * @return TEEC_SUCCESS OpenSession successfully opened a new session. 120 | * @return TEEC_Result Something failed. 121 | */ 122 | TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, 123 | uint32_t commandID, 124 | TEEC_Operation *operation, 125 | uint32_t *returnOrigin); 126 | 127 | /** 128 | * TEEC_RegisterSharedMemory() - Register a block of existing memory as a 129 | * shared block within the scope of the specified context. 130 | * 131 | * @param context The initialized TEE context structure in which scope to 132 | * open the session. 133 | * @param sharedMem pointer to the shared memory structure to register. 134 | * 135 | * @return TEEC_SUCCESS The registration was successful. 136 | * @return TEEC_ERROR_OUT_OF_MEMORY Memory exhaustion. 137 | * @return TEEC_Result Something failed. 138 | */ 139 | TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context, 140 | TEEC_SharedMemory *sharedMem); 141 | 142 | /** 143 | * TEEC_AllocateSharedMemory() - Allocate shared memory for TEE. 144 | * 145 | * @param context The initialized TEE context structure in which scope to 146 | * open the session. 147 | * @param sharedMem Pointer to the allocated shared memory. 148 | * 149 | * @return TEEC_SUCCESS The registration was successful. 150 | * @return TEEC_ERROR_OUT_OF_MEMORY Memory exhaustion. 151 | * @return TEEC_Result Something failed. 152 | */ 153 | TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context, 154 | TEEC_SharedMemory *sharedMem); 155 | 156 | /** 157 | * TEEC_ReleaseSharedMemory() - Free or deregister the shared memory. 158 | * 159 | * @param sharedMem Pointer to the shared memory to be freed. 160 | */ 161 | void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *sharedMemory); 162 | 163 | #if 0 164 | /** 165 | * TEEC_RequestCancellation() - Request the cancellation of a pending open 166 | * session or command invocation. 167 | * 168 | * @param operation Pointer to an operation previously passed to open session 169 | * or invoke. 170 | */ 171 | void TEEC_RequestCancellation(TEEC_Operation *operation); 172 | #endif 173 | 174 | #endif 175 | --------------------------------------------------------------------------------