├── .gitignore ├── Android.bp ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── COPYING ├── LICENSE-BSD-3-CLAUSE ├── LICENSE-GPL2 ├── Makefile ├── README.md ├── add_symbol.S ├── stm32wrapper4dbg.1 ├── stm32wrapper4dbg.c ├── wrapper_stm32mp13x_ca7.c ├── wrapper_stm32mp13x_ca7.inc ├── wrapper_stm32mp15x_ca7.c ├── wrapper_stm32mp15x_ca7.inc ├── wrapper_stm32mp21x_ca35.c ├── wrapper_stm32mp21x_ca35.inc ├── wrapper_stm32mp21x_cm33.c ├── wrapper_stm32mp21x_cm33.inc ├── wrapper_stm32mp25x_ca35.c ├── wrapper_stm32mp25x_ca35.inc ├── wrapper_stm32mp25x_cm33.c └── wrapper_stm32mp25x_cm33.inc /.gitignore: -------------------------------------------------------------------------------- 1 | stm32wrapper4dbg 2 | wrapper_stm32mp*.bin 3 | wrapper_stm32mp*.elf 4 | wrapper_stm32mp*.s 5 | -------------------------------------------------------------------------------- /Android.bp: -------------------------------------------------------------------------------- 1 | cc_binary_host { 2 | name: "stm32wrapper4dbg", 3 | cflags: [ 4 | "-Wall", 5 | "-Werror", 6 | "-Wno-sign-compare", 7 | "-Wno-missing-field-initializers", 8 | "-Wno-unused-parameter", 9 | ], 10 | srcs: [ 11 | "stm32wrapper4dbg.c", 12 | ], 13 | stl: "none", 14 | } 15 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team via this [link](https://www.st.com/content/st_com/en/contact-us.html). 59 | All complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, 71 | available [here](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html). 72 | 73 | For answers to common questions about this code of conduct, refer to the FAQ section [here](https://www.contributor-covenant.org/faq). 74 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing guide 2 | 3 | This document serves as a checklist before contributing to this repository. 4 | It includes links to read up on if topics are unclear to you. 5 | 6 | This guide mainly focuses on the proper use of Git. 7 | 8 | ## 1. Issues 9 | 10 | STM32MPU projects do not activate "Github issues" feature for the time being. 11 | If you need to report an issue or question about this project deliverables, 12 | you can report them using 13 | [ ST Support Center ](https://my.st.com/ols#/ols/newrequest) 14 | or 15 | [ ST Community MPU Forum ](https://community.st.com/s/topic/0TO0X0000003u2AWAQ/stm32-mpus). 16 | 17 | ## 2. Pull Requests 18 | 19 | STMicroelectronics is happy to receive contributions from the community, based 20 | on an initial Contributor License Agreement (CLA) procedure. 21 | 22 | * If you are an individual writing original source code and you are sure 23 | **you own the intellectual property**, then you need to sign an Individual 24 | CLA (https://cla.st.com). 25 | * If you work for a company that wants also to allow you to contribute with 26 | your work, your company needs to provide a Corporate CLA 27 | (https://cla.st.com) mentioning your GitHub account name. 28 | * If you are not sure that a CLA (Individual or Corporate) has been signed for 29 | your GitHub account you can check here (https://cla.st.com). 30 | 31 | Please note that: 32 | * The Corporate CLA will always take precedence over the Individual CLA. 33 | * One CLA submission is sufficient, for any project proposed by 34 | STMicroelectronics. 35 | 36 | __How to proceed__ 37 | 38 | * We recommend to fork the project in your GitHub account to further develop 39 | your contribution. Please use the latest commit version. 40 | * Please, submit one Pull Request for one new feature or proposal. This will 41 | ease the analysis and final merge if accepted. 42 | 43 | __Note__ 44 | 45 | Merge will not be done directly in GitHub but it will need first to follow 46 | internal integration process before public deliver in a standard release. 47 | The Pull request will stay open until it is merged and delivered. 48 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved 2 | 3 | This work is dual-licensed under the terms of the General Public 4 | License (GPL) Version 2 (or any later version) or under the terms 5 | of the BSD 3-Clause "New" or "Revised" License. 6 | You may use this work according to one of these licenses, as is 7 | most appropriate for your project, on a case-by-case basis. 8 | 9 | The terms of each license is distributed in the main directory of 10 | the source code repository and is available on-line from: 11 | 12 | GPL2 License: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 13 | BSD 3-Clause License: https://opensource.org/licenses/BSD-3-Clause 14 | -------------------------------------------------------------------------------- /LICENSE-BSD-3-CLAUSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2020, STMicroelectronics 2 | 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 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. 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 | 3. Neither the name of the copyright holder nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific 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 ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /LICENSE-GPL2: -------------------------------------------------------------------------------- 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 | # SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause 2 | # Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved 3 | 4 | CROSS_COMPILE_ARM32 = arm-none-eabi- 5 | CROSS_COMPILE_ARM64 = aarch64-linux-gnu- 6 | 7 | # Without cross compiler, don't remove or rebuild it 8 | xtool_32_missing := $(shell type -t $(CROSS_COMPILE_ARM32){gcc,objdump} > /dev/null; echo $$?) 9 | xtool_64_missing := $(shell type -t $(CROSS_COMPILE_ARM64){gcc,objdump} > /dev/null; echo $$?) 10 | 11 | # Without cross compiler, don't remove or rebuild it 12 | ifeq ($(xtool_32_missing),0) 13 | extra_dep := wrapper_stm32mp13x_ca7.inc wrapper_stm32mp15x_ca7.inc wrapper_stm32mp21x_cm33.inc wrapper_stm32mp25x_cm33.inc 14 | extra_cln := wrapper_stm32mp13x_ca7.s wrapper_stm32mp15x_ca7.s wrapper_stm32mp21x_cm33.s wrapper_stm32mp25x_cm33.s 15 | else 16 | extra_dep := 17 | extra_cln := 18 | endif 19 | 20 | ifeq ($(xtool_64_missing),0) 21 | extra_dep += wrapper_stm32mp21x_ca35.inc wrapper_stm32mp25x_ca35.inc 22 | extra_cln += wrapper_stm32mp21x_ca35.s wrapper_stm32mp25x_ca35.s 23 | endif 24 | 25 | stm32wrapper4dbg: stm32wrapper4dbg.c $(extra_dep) 26 | $(CC) -O2 $(CFLAGS) $(LDFLAGS) -Wall -Wextra $< -o $@ 27 | 28 | %.inc: %.bin 29 | echo '/* Generated automatically by Makefile */' > $@ 30 | od -v -A n -t x1 $< | sed 's/ *\(..\) */0x\1,/g' >> $@ 31 | 32 | %_ca7.bin: %_ca7.elf 33 | $(CROSS_COMPILE_ARM32)objcopy -O binary $< $@ 34 | 35 | %_cm33.bin: %_cm33.elf 36 | $(CROSS_COMPILE_ARM32)objcopy -O binary $< $@ 37 | 38 | %_ca35.bin: %_ca35.elf 39 | $(CROSS_COMPILE_ARM64)objcopy -R .eh_frame -O binary $< $@ 40 | 41 | %_ca7.s: %_ca7.c 42 | $(CROSS_COMPILE_ARM32)gcc -Wall -Werror -Wstack-usage=0 -Os -g -fcall-used-r4 -fcall-used-r5 -ffixed-r7 -ffixed-r11 -ffixed-r14 -fconserve-stack -fomit-frame-pointer -mcpu=cortex-a7 -mthumb -S $< -o $@ 43 | 44 | %_ca7.elf: %_ca7.s add_symbol.S 45 | $(CROSS_COMPILE_ARM32)gcc -Wall -Werror -static -g -mcpu=cortex-a7 -mthumb -nostartfiles -Wl,-n -Wl,-Ttext,0x2ffc2500 -DASM_FILE=\"$<\" add_symbol.S -o $@ 46 | 47 | #%_ca7.elf: %_ca7.S 48 | # $(CROSS_COMPILE_ARM32)gcc -Wall -static -nostartfiles -mlittle-endian -Wa,-EL -Wl,-n -Wl,-Ttext,0x2ffc2500 $< -o $@ 49 | 50 | %_cm33.s: %_cm33.c 51 | $(CROSS_COMPILE_ARM32)gcc -Wall -Werror -Wstack-usage=0 -Os -g -fcall-used-r4 -fcall-used-r5 -ffixed-r7 -ffixed-r11 -ffixed-r14 -fconserve-stack -fomit-frame-pointer -mcpu=cortex-m33 -mthumb -S $< -o $@ 52 | 53 | %_cm33.elf: %_cm33.s add_symbol.S 54 | $(CROSS_COMPILE_ARM32)gcc -Wall -Werror -static -g -mcpu=cortex-m33 -mthumb -nostartfiles -Wl,-n -Wl,-Ttext,0x0e080000 -DASM_FILE=\"$<\" add_symbol.S -o $@ 55 | 56 | %_ca35.s: %_ca35.c 57 | $(CROSS_COMPILE_ARM64)gcc -Wall -Werror -Wstack-usage=0 -Os -g -fcall-used-x19 -fcall-used-x20 -fcall-used-x21 -fcall-used-x22 -fcall-used-x23 -fcall-used-x24 -fcall-used-x25 -fcall-used-x26 -fcall-used-x27 -fcall-used-x28 -fconserve-stack -fomit-frame-pointer -ffixed-x30 -mcpu=cortex-a35 -S $< -o $@ 58 | 59 | %_ca35.elf: %_ca35.s add_symbol.S 60 | $(CROSS_COMPILE_ARM64)gcc -Wall -Werror -static -g -mcpu=cortex-a35 -nostartfiles -Wl,-n -Wl,-Ttext,0x0e012000 -Wl,--build-id=none -DASM_FILE=\"$<\" add_symbol.S -o $@ 61 | 62 | .PRECIOUS: %_ca7.bin %_ca35.bin %_cm33.bin %_ca7.elf %_ca35.elf %_cm33.elf %_ca7.s %_ca35.s %_cm33.s 63 | 64 | clean: 65 | rm -f stm32wrapper4dbg wrapper_stm32*.bin wrapper_stm32mp*.elf $(extra_dep) $(extra_cln) 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # stm32wrapper4dbg 2 | 3 | A tool that adds a debug wrapper to a stm32 fsbl image. 4 | 5 | ## Tool description 6 | 7 | To handle secure boot, **STM32 MPU** prevents the debugger to halt 8 | the system at reset vector. 9 | This cause the debugger to halt each core at a random address, as 10 | soon as it get access to the debug port. 11 | Such random halt address is not optimal to debug the early boot 12 | steps of either the *First-Stage Boot Loader* (fsbl) 13 | (e.g. **TF-A**) or the *Second-Stage Boot Loader* 14 | (e.g. **U-Boot**). 15 | 16 | A common workaround consists by adding an infinite loop at the 17 | entry of fsbl, so the debugger can attach, halt and skip the loop. 18 | This has the drawback of requiring modification in the source code 19 | of fsbl. 20 | 21 | *stm32wrapper4dbg* adds a binary wrapper to an existing fsbl image 22 | in *stm32 binary format* and generates a new wrapped stm32 image. 23 | The wrapped image is intended to replace the existing fsbl image 24 | flashed on **STM32 MPU** board during the debug activity. 25 | 26 | The wrapper code is executed before the fsbl code and: 27 | 28 | * enables the debug port (JTAG and SWD); 29 | * waits at maximum two seconds for a debugger to attach and to 30 | toggle *debug claim* bit zero, then jumps to fsbl; 31 | * if the debugger *has requested to halt*, then the boot will 32 | halt at the very first instruction of fsbl. If no debugger is 33 | detected or the debugger has not requested any halt, the fsbl 34 | is executed. 35 | 36 | **ATTENTION:** on devices *closed* with OTP, the debug port is not 37 | accessible, for obvious security reasons. A wrapped image created 38 | with *stm32wrapper4dbg* will **open the debug port**. A wrapped 39 | image must be signed with the user key to be used in the secured 40 | boot. **Do not distribute the signed wrapped image** to prevent 41 | its use to compromise the secure boot. 42 | 43 | ## Getting Started 44 | 45 | ### Prerequisite 46 | 47 | The fsbl in *stm32 binary image* format must be available. 48 | 49 | ### Installing 50 | 51 | Simply run: 52 | 53 | ``` 54 | make 55 | ``` 56 | 57 | then copy the file *stm32wrapper4dbg* and the man page file 58 | *stm32wrapper4dbg.1*. 59 | 60 | ### Running stm32wrapper4dbg 61 | 62 | Check the man page *stm32wrapper4dbg (1)* for syntax and examples. 63 | 64 | ## Contributing 65 | 66 | See contributing.md for contribution guidelines to *stm32wrapper4dbg*. 67 | 68 | ## Maintainers 69 | 70 | * Antonio Borneo 71 | 72 | ## License 73 | 74 | The tool *stm32wrapper4dbg* is dual-licensed under 75 | *GPL-2.0-or-later* **OR** *BSD-3-Clause*. 76 | 77 | You may use this work according to either of these licenses as is 78 | most appropriate for your project on a case-by-case basis. 79 | -------------------------------------------------------------------------------- /add_symbol.S: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ 2 | /* 3 | * Copyright (c) 2024, STMicroelectronics - All Rights Reserved 4 | * Author: Antonio Borneo 5 | */ 6 | 7 | /* 8 | * This file is used to add the label 'fsbl_ptr' at the end of an assembly 9 | * file. The label will be used as it was one of the 'literals' of the last 10 | * function of the assembly file, thus allowing PC relative loading of the 11 | * data at the label's address. 12 | */ 13 | 14 | #include ASM_FILE 15 | 16 | .text 17 | .align 2 18 | fsbl_ptr: 19 | -------------------------------------------------------------------------------- /stm32wrapper4dbg.1: -------------------------------------------------------------------------------- 1 | .\" SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause 2 | .TH STM32WRAPPER4DBG 1 "2021-01-16" 3 | 4 | .SH NAME 5 | stm32wrapper4dbg \- Add debug wrapper to a stm32 fsbl image 6 | 7 | .SH SYNOPSIS 8 | .B stm32wrapper4dbg 9 | .RB "" "\-s " "\fIsrcimage\fP" " \-d " "\fIdstimage\fP [" "\-b" "] [" "\-f" "]" 10 | .P 11 | .B stm32wrapper4dbg 12 | .RB "" "\-V" 13 | 14 | .SH "DESCRIPTION" 15 | The 16 | .B stm32wrapper4dbg 17 | command is used to add a debug wrapper around the 18 | .B first stage boot loader 19 | (fsbl) images for the 20 | .B STM32MPxxx 21 | processor family. 22 | The wrapper opens the debug port to allow debugging all the software 23 | components in the boot chain. 24 | 25 | The wrapped image will be loaded at the same memory addresses of the 26 | original image, thus preserving the address of all the symbols. 27 | 28 | The wrapper requires less then 64 bytes; the original image should be 29 | smaller than the available memory to allow both wrapper and image to be 30 | loaded together. 31 | 32 | By default the wrapper is loaded in memory 33 | .B after 34 | the image, so the image in \fIdstimage\fP will start at the same memory 35 | address of \fIsrcimage\fP. 36 | 37 | .SH "OPTIONS" 38 | .TP 39 | .BI "\-s " "\fIsrcimage\fP" 40 | Read the fsbl image to be wrapped from \fIsrcimage\fP file. 41 | 42 | .TP 43 | .BI "\-d " "\fIdstimage\fP" 44 | Write the wrapped fsbl image in \fIdstimage\fP file. 45 | 46 | .TP 47 | .BI "\-b" 48 | Add the wrapper 49 | .B before 50 | the image. The image in \fIdstimage\fP will end at the same memory address 51 | of \fIsrcimage\fP. 52 | 53 | .TP 54 | .BI "\-f" 55 | Force adding an additional instance of the wrapper to an image file that 56 | already contains the wrapper. 57 | 58 | .TP 59 | .BI "\-V" 60 | Display tool version and quit. 61 | 62 | .SH EXAMPLES 63 | Wrap the image in a file, then write it to the first partition of the SD card: 64 | .sp 65 | .RS 4 66 | .nf 67 | \fB 68 | stm32wrapper4dbg -f fsbl.stm32 -d wrapped.stm32 69 | dd if=wrapped.stm32 of=/dev/sdd1 70 | .fi \fR 71 | .P 72 | .RE 73 | .P 74 | Wrap the image in the second partition of the SD card and write it to the first partition of the same SD card: 75 | .sp 76 | .RS 4 77 | .nf 78 | \fB 79 | stm32wrapper4dbg -f /dev/sdd2 -d /dev/sdd1 80 | .fi \fR 81 | .P 82 | .RE 83 | .P 84 | 85 | .SH AUTHORS 86 | Antonio Borneo 87 | 88 | .SH COPYRIGHT 89 | Copyright \(co 2020-2021 STMicroelectronics - All Rights Reserved 90 | .br 91 | This is free software; see the source for copying conditions. There is NO 92 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 93 | -------------------------------------------------------------------------------- /stm32wrapper4dbg.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause 2 | 3 | /* 4 | * Copyright (c) 2017-2024, STMicroelectronics - All Rights Reserved 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #define VERSION "5.0.2" 23 | 24 | /* Magic = 'S' 'T' 'M' 0x32 */ 25 | #define HEADER_MAGIC 0x53544D32 26 | #define HEADER_VERSION_V10 0x00010000 27 | #define HEADER_VERSION_V20 0x00020000 28 | #define HEADER_VERSION_V22 0x00020200 29 | #define HEADER_VERSION_V23 0x00020300 30 | #define PADDING_HEADER_MAGIC 0x5354FFFF 31 | #define PADDING_HEADER_FLAG (1 << 31) 32 | #define BIN_TYPE_TF_A_IMAGE 0x10 33 | #define BIN_TYPE_CM33_IMAGE 0x30 34 | 35 | #define ARM_THUMB_ADDRESS(a) ((a) | 1) 36 | #define ARM_THUMB_INSN(a) ((a) & ~1) 37 | #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) 38 | #define ALIGN_DOWN(x, a) ((x) & ~((a) - 1)) 39 | #define WRAPPER_ALIGNMENT 64UL 40 | 41 | #define LOG_DEBUG(x ...) do { if (verbose) printf(x); } while (0) 42 | #define LOG_INFO(x ...) printf(x) 43 | #define LOG_ERROR(x ...) fprintf(stderr, x) 44 | 45 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) 46 | 47 | #define STM32_DUMMY_FW_LENGTH 16 48 | 49 | static uint8_t stm32_mp13_ca7_wrapper[] = { 50 | #include "wrapper_stm32mp13x_ca7.inc" 51 | }; 52 | 53 | static uint8_t stm32_mp15_ca7_wrapper[] = { 54 | #include "wrapper_stm32mp15x_ca7.inc" 55 | }; 56 | 57 | static uint8_t stm32_mp2_ca35_wrapper[] = { 58 | #include "wrapper_stm32mp25x_ca35.inc" 59 | }; 60 | 61 | static uint8_t stm32_mp2_cm33_wrapper[] = { 62 | #include "wrapper_stm32mp25x_cm33.inc" 63 | }; 64 | 65 | static uint8_t stm32_mp21_ca35_wrapper[] = { 66 | #include "wrapper_stm32mp21x_ca35.inc" 67 | }; 68 | 69 | static uint8_t stm32_mp21_cm33_wrapper[] = { 70 | #include "wrapper_stm32mp21x_cm33.inc" 71 | }; 72 | 73 | static bool verbose; 74 | 75 | struct stm32_header_v10 { 76 | uint32_t magic_number; 77 | uint8_t image_signature[64]; 78 | uint32_t image_checksum; 79 | uint32_t header_version; 80 | uint32_t image_length; 81 | uint32_t image_entry_point; 82 | uint32_t reserved1; 83 | uint32_t load_address; 84 | uint32_t reserved2; 85 | uint32_t version_number; 86 | uint32_t option_flags; 87 | uint32_t ecdsa_algorithm; 88 | uint8_t ecdsa_public_key[64]; 89 | uint8_t padding[83]; 90 | uint8_t binary_type; 91 | }; 92 | 93 | struct stm32_header_v2x { 94 | uint32_t magic_number; 95 | uint8_t image_signature[64]; 96 | uint32_t image_checksum; 97 | uint32_t header_version; 98 | uint32_t image_length; 99 | uint32_t image_entry_point; 100 | uint32_t reserved1; 101 | uint32_t load_address; 102 | uint32_t reserved2; 103 | uint32_t version_number; 104 | uint32_t extension_flags; 105 | uint32_t post_headers_length; 106 | uint32_t binary_type; 107 | uint8_t padding[16]; 108 | uint32_t extension_header_type; 109 | uint32_t extension_header_length; 110 | uint8_t extension_padding[376]; 111 | }; 112 | 113 | struct stm32_header_v23 { 114 | uint32_t magic_number; 115 | uint8_t image_signature[96]; 116 | uint32_t image_checksum; 117 | uint32_t header_version; 118 | uint32_t image_length; 119 | uint32_t image_entry_point; 120 | uint32_t reserved1; 121 | uint32_t load_address; 122 | uint32_t reserved2; 123 | uint32_t version_number; 124 | uint32_t extension_flags; 125 | uint32_t post_headers_length; 126 | uint32_t binary_type; 127 | uint8_t padding[8]; 128 | uint32_t non_secure_payload_length; 129 | uint32_t non_secure_payload_hash; 130 | uint32_t extension_header_type; 131 | uint32_t extension_header_length; 132 | uint8_t extension_padding[408]; 133 | }; 134 | 135 | /* big enough for padding and all header types */ 136 | static const uint8_t zero_buffer[2048]; 137 | 138 | struct stm32_soc { 139 | const char *name; 140 | uint32_t header_version; 141 | uint32_t binary_type; 142 | uint32_t mem_start; 143 | uint32_t mem_end; 144 | const uint8_t *wrapper; 145 | unsigned int wrapper_size; 146 | bool wrapper_is_arm_thumb; 147 | const char *dummy_name; 148 | uint8_t *dummy_fw; 149 | }; 150 | 151 | struct stm32_file { 152 | void *p; 153 | const struct stm32_soc *soc; 154 | int fd; 155 | size_t file_size; 156 | uint32_t file_header_length; 157 | uint32_t image_length; 158 | uint32_t image_entry_point; 159 | uint32_t load_address; 160 | uint32_t version_number; 161 | bool is_signed; 162 | bool is_encrypted; 163 | }; 164 | 165 | /* 166 | * dummy code for armv7m thumb (CM33) 167 | * .word 0xXXXX0200 // SP 168 | * .word 0xXXXX0009 // reset 169 | * bf00 nop 170 | * bf00 nop 171 | * bf00 nop 172 | * label: 173 | * e7fe b label 174 | */ 175 | static uint8_t stm32_dummy_fw_m33_thumb[STM32_DUMMY_FW_LENGTH] = { 176 | 0x00, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xbf, 0xfe, 0xe7, 177 | }; 178 | 179 | /* 180 | * dummy code for aarch32 thumb (CA7) 181 | * bf00 nop 182 | * bf00 nop 183 | * bf00 nop 184 | * bf00 nop 185 | * bf00 nop 186 | * bf00 nop 187 | * bf00 nop 188 | * label: 189 | * e7fe b label 190 | */ 191 | static uint8_t stm32_dummy_fw_a32_thumb[STM32_DUMMY_FW_LENGTH] = { 192 | 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xbf, 0xfe, 0xe7, 193 | }; 194 | 195 | /* 196 | * dummy code for aarch64 (CA35) 197 | * d503201f nop 198 | * d503201f nop 199 | * d503201f nop 200 | * label: 201 | * 14000000 b label 202 | */ 203 | static uint8_t stm32_dummy_fw_a64[STM32_DUMMY_FW_LENGTH] = { 204 | 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x00, 0x00, 0x00, 0x14, 205 | }; 206 | 207 | static const struct stm32_soc stm32_socs[] = { 208 | { 209 | .name = "STM32MP13x Cortex-A7", 210 | .header_version = HEADER_VERSION_V20, 211 | .binary_type = BIN_TYPE_TF_A_IMAGE, 212 | .mem_start = 0x2FFE0000, 213 | .mem_end = 0x30000000, 214 | .wrapper = stm32_mp13_ca7_wrapper, 215 | .wrapper_size = ARRAY_SIZE(stm32_mp13_ca7_wrapper), 216 | .wrapper_is_arm_thumb = true, 217 | .dummy_name = "dummy-mp13-ca7", 218 | .dummy_fw = stm32_dummy_fw_a32_thumb, 219 | }, { 220 | .name = "STM32MP15x Cortex-A7", 221 | .header_version = HEADER_VERSION_V10, 222 | .binary_type = BIN_TYPE_TF_A_IMAGE, 223 | .mem_start = 0x2FFC0000, 224 | .mem_end = 0x30000000, 225 | .wrapper = stm32_mp15_ca7_wrapper, 226 | .wrapper_size = ARRAY_SIZE(stm32_mp15_ca7_wrapper), 227 | .wrapper_is_arm_thumb = true, 228 | .dummy_name = "dummy-mp15-ca7", 229 | .dummy_fw = stm32_dummy_fw_a32_thumb, 230 | }, { 231 | .name = "STM32MP2[35]x Cortex-A35", 232 | .header_version = HEADER_VERSION_V22, 233 | .binary_type = BIN_TYPE_TF_A_IMAGE, 234 | .mem_start = 0x0E002600, 235 | .mem_end = 0x0E040000, 236 | .wrapper = stm32_mp2_ca35_wrapper, 237 | .wrapper_size = ARRAY_SIZE(stm32_mp2_ca35_wrapper), 238 | .wrapper_is_arm_thumb = false, 239 | .dummy_name = "dummy-mp25-ca35", 240 | .dummy_fw = stm32_dummy_fw_a64, 241 | }, { 242 | .name = "STM32MP2[35]x Cortex-M33", 243 | .header_version = HEADER_VERSION_V22, 244 | .binary_type = BIN_TYPE_CM33_IMAGE, 245 | .mem_start = 0x0E080000, 246 | .mem_end = 0x0E0A0000, 247 | .wrapper = stm32_mp2_cm33_wrapper, 248 | .wrapper_size = ARRAY_SIZE(stm32_mp2_cm33_wrapper), 249 | .wrapper_is_arm_thumb = true, 250 | .dummy_name = "dummy-mp25-cm33", 251 | .dummy_fw = stm32_dummy_fw_m33_thumb, 252 | }, { 253 | .name = "STM32MP21x Cortex-A35", 254 | .header_version = HEADER_VERSION_V23, 255 | .binary_type = BIN_TYPE_TF_A_IMAGE, 256 | .mem_start = 0x0E002640, 257 | .mem_end = 0x0E040000, 258 | .wrapper = stm32_mp21_ca35_wrapper, 259 | .wrapper_size = ARRAY_SIZE(stm32_mp21_ca35_wrapper), 260 | .wrapper_is_arm_thumb = false, 261 | .dummy_name = "dummy-mp21-ca35", 262 | .dummy_fw = stm32_dummy_fw_a64, 263 | }, { 264 | .name = "STM32MP21x Cortex-M33", 265 | .header_version = HEADER_VERSION_V23, 266 | .binary_type = BIN_TYPE_CM33_IMAGE, 267 | .mem_start = 0x0E040000, 268 | .mem_end = 0x0E060000, 269 | .wrapper = stm32_mp21_cm33_wrapper, 270 | .wrapper_size = ARRAY_SIZE(stm32_mp21_cm33_wrapper), 271 | .wrapper_is_arm_thumb = true, 272 | .dummy_name = "dummy-mp21-cm33", 273 | .dummy_fw = stm32_dummy_fw_m33_thumb, 274 | }, 275 | }; 276 | 277 | static uint32_t stm32_checksum(const uint8_t *p, uint32_t len) 278 | { 279 | uint32_t csum = 0; 280 | 281 | while (len > 0) { 282 | csum += *p; 283 | p++; 284 | len--; 285 | } 286 | 287 | return csum; 288 | } 289 | 290 | static int stm32image_check_hdr(struct stm32_file *f, uint32_t file_length) 291 | { 292 | const struct stm32_header_v10 *h10 = f->p; 293 | const struct stm32_header_v2x *h2x = f->p; 294 | const struct stm32_header_v23 *h23 = f->p; 295 | const uint8_t *p = f->p; 296 | uint32_t header_length, magic_number, image_checksum, header_version; 297 | uint32_t image_length, image_entry_point; 298 | uint32_t load_address, reserved1, reserved2, version_number, flags, post_headers_length, binary_type; 299 | unsigned int padding_start, padding_size; 300 | bool is_signed, is_encrypted; 301 | unsigned int i, j; 302 | 303 | for (i = 0; i < ARRAY_SIZE(stm32_socs); i++) { 304 | LOG_DEBUG("Checking for soc \"%s\"\n", stm32_socs[i].name); 305 | 306 | switch (stm32_socs[i].header_version) { 307 | case HEADER_VERSION_V10: 308 | header_length = sizeof(*h10); 309 | break; 310 | case HEADER_VERSION_V20: 311 | case HEADER_VERSION_V22: 312 | header_length = sizeof(*h2x); 313 | break; 314 | case HEADER_VERSION_V23: 315 | header_length = sizeof(*h23); 316 | break; 317 | default: 318 | continue; 319 | } 320 | 321 | if (file_length < header_length) { 322 | LOG_DEBUG("File too small\n"); 323 | continue; 324 | } 325 | 326 | switch (stm32_socs[i].header_version) { 327 | case HEADER_VERSION_V10: 328 | magic_number = __be32_to_cpu(h10->magic_number); 329 | image_checksum = __le32_to_cpu(h10->image_checksum); 330 | header_version = __le32_to_cpu(h10->header_version); 331 | image_length = __le32_to_cpu(h10->image_length); 332 | image_entry_point = __le32_to_cpu(h10->image_entry_point); 333 | load_address = __le32_to_cpu(h10->load_address); 334 | reserved1 = h10->reserved1; 335 | reserved2 = h10->reserved2; 336 | version_number = __le32_to_cpu(h10->version_number); 337 | flags = __le32_to_cpu(h10->option_flags); 338 | post_headers_length = header_length; 339 | binary_type = h10->binary_type; 340 | padding_start = offsetof(typeof(*h10), padding); 341 | padding_size = sizeof(h10->padding); 342 | is_signed = (flags & 1) == 0; 343 | is_encrypted = false; 344 | break; 345 | 346 | case HEADER_VERSION_V20: 347 | case HEADER_VERSION_V22: 348 | magic_number = __be32_to_cpu(h2x->magic_number); 349 | image_checksum = __le32_to_cpu(h2x->image_checksum); 350 | header_version = __le32_to_cpu(h2x->header_version); 351 | image_length = __le32_to_cpu(h2x->image_length); 352 | image_entry_point = __le32_to_cpu(h2x->image_entry_point); 353 | load_address = __le32_to_cpu(h2x->load_address); 354 | reserved1 = h2x->reserved1; 355 | reserved2 = h2x->reserved2; 356 | version_number = __le32_to_cpu(h2x->version_number); 357 | flags = __le32_to_cpu(h2x->extension_flags); 358 | post_headers_length = __le32_to_cpu(h2x->post_headers_length) + 359 | offsetof(typeof(*h2x), extension_header_type); 360 | binary_type = __le32_to_cpu(h2x->binary_type); 361 | padding_start = offsetof(typeof(*h2x), padding); 362 | padding_size = sizeof(h2x->padding); 363 | is_signed = (flags & 1) != 0; 364 | is_encrypted = (flags & 2) != 0; 365 | break; 366 | 367 | case HEADER_VERSION_V23: 368 | default: 369 | magic_number = __be32_to_cpu(h23->magic_number); 370 | image_checksum = __le32_to_cpu(h23->image_checksum); 371 | header_version = __le32_to_cpu(h23->header_version); 372 | image_length = __le32_to_cpu(h23->image_length); 373 | image_entry_point = __le32_to_cpu(h23->image_entry_point); 374 | load_address = __le32_to_cpu(h23->load_address); 375 | reserved1 = h23->reserved1; 376 | reserved2 = h23->reserved2; 377 | version_number = __le32_to_cpu(h23->version_number); 378 | flags = __le32_to_cpu(h23->extension_flags); 379 | post_headers_length = __le32_to_cpu(h23->post_headers_length) + 380 | offsetof(typeof(*h23), extension_header_type); 381 | binary_type = __le32_to_cpu(h23->binary_type); 382 | padding_start = offsetof(typeof(*h23), padding); 383 | padding_size = sizeof(h23->padding); 384 | is_signed = (flags & 1) != 0; 385 | is_encrypted = (flags & 2) != 0; 386 | break; 387 | } 388 | 389 | if (magic_number != HEADER_MAGIC) { 390 | LOG_DEBUG("Wrong header magic\n"); 391 | continue; 392 | } 393 | 394 | if (header_version != stm32_socs[i].header_version) { 395 | LOG_DEBUG("Wrong header version\n"); 396 | continue; 397 | } 398 | 399 | if (binary_type != stm32_socs[i].binary_type) { 400 | LOG_DEBUG("Wrong header binary type\n"); 401 | continue; 402 | } 403 | 404 | if (file_length < header_length + image_length) { 405 | LOG_DEBUG("File too small\n"); 406 | continue; 407 | } 408 | 409 | if (header_length != post_headers_length) { 410 | LOG_DEBUG("Wrong header size\n"); 411 | continue; 412 | } 413 | 414 | if (image_checksum != stm32_checksum(p + header_length, image_length)) { 415 | LOG_DEBUG("Wrong image checksum\n"); 416 | continue; 417 | } 418 | 419 | if (reserved1 || reserved2) { 420 | LOG_DEBUG("Wrong image, reserved fields not zero\n"); 421 | continue; 422 | } 423 | 424 | for (j = 0; j < padding_size; j++) 425 | if (p[padding_start + j]) 426 | break; 427 | 428 | if (j < padding_size) { 429 | LOG_DEBUG("Wrong image, padding not zero\n"); 430 | continue; 431 | } 432 | 433 | if ((image_entry_point < load_address) || 434 | (image_entry_point >= load_address + image_length)) { 435 | LOG_DEBUG("Wrong image entry point\n"); 436 | continue; 437 | } 438 | 439 | if ((load_address < stm32_socs[i].mem_start) || 440 | (load_address + image_length > stm32_socs[i].mem_end)) { 441 | LOG_DEBUG("Image doesn't fit in memory\n"); 442 | continue; 443 | } 444 | 445 | if (binary_type == BIN_TYPE_CM33_IMAGE && 446 | image_length >= 8 && 447 | image_entry_point != __le32_to_cpu(*(uint32_t *)(p + header_length + 4))) { 448 | LOG_DEBUG("Image entry point mismatches reset vector\n"); 449 | continue; 450 | } 451 | 452 | f->soc = &stm32_socs[i]; 453 | f->file_header_length = header_length; 454 | f->image_length = image_length; 455 | f->image_entry_point = image_entry_point; 456 | f->load_address = load_address; 457 | f->version_number = version_number; 458 | f->is_signed = is_signed; 459 | f->is_encrypted = is_encrypted; 460 | 461 | return 0; 462 | } 463 | 464 | return -1; 465 | } 466 | 467 | static int stm32image_check_wrapper(const struct stm32_file *f) 468 | { 469 | uint32_t entry, offset; 470 | uint8_t *ptr; 471 | 472 | entry = ARM_THUMB_INSN(f->image_entry_point); 473 | 474 | offset = entry - f->load_address; 475 | if (offset + f->soc->wrapper_size + sizeof(uint32_t) > f->image_length) 476 | return 0; 477 | 478 | ptr = f->p; 479 | if (memcmp(ptr + f->file_header_length + offset, f->soc->wrapper, f->soc->wrapper_size)) 480 | return 0; 481 | 482 | return -1; 483 | } 484 | 485 | static void stm32image_print_header(const struct stm32_file *f) 486 | { 487 | LOG_INFO("Image Type : STMicroelectronics STM32 V%d.%d\n", 488 | (f->soc->header_version >> 16) & 0xFF, 489 | (f->soc->header_version >> 8) & 0xFF); 490 | LOG_INFO("Image Target : %s\n", f->soc->name); 491 | LOG_INFO("Image Size : %u bytes\n", f->image_length); 492 | LOG_INFO("Image Load : 0x%08x\n", f->load_address); 493 | LOG_INFO("Entry Point : 0x%08x\n", f->image_entry_point); 494 | LOG_INFO("Version : 0x%08x\n", f->version_number); 495 | } 496 | 497 | static int stm32image_update_header(const struct stm32_file *f) 498 | { 499 | struct stm32_header_v10 *h10 = f->p; 500 | struct stm32_header_v2x *h2x = f->p; 501 | struct stm32_header_v23 *h23 = f->p; 502 | uint8_t *p = f->p; 503 | uint32_t crc, extension_length; 504 | 505 | if (f->soc->binary_type == BIN_TYPE_CM33_IMAGE) 506 | *(uint32_t *)(p + f->file_header_length + 4) = __cpu_to_le32(f->image_entry_point); 507 | 508 | crc = stm32_checksum(p + f->file_header_length, f->image_length); 509 | 510 | switch (f->soc->header_version) { 511 | case HEADER_VERSION_V10: 512 | h10->magic_number = __cpu_to_be32(HEADER_MAGIC); 513 | h10->version_number = __cpu_to_le32(f->version_number); 514 | h10->header_version = __cpu_to_le32(f->soc->header_version); 515 | h10->binary_type = f->soc->binary_type; 516 | h10->option_flags = __cpu_to_le32(0x00000001); 517 | h10->ecdsa_algorithm = __cpu_to_le32(1); 518 | h10->image_length = __cpu_to_le32(f->image_length); 519 | h10->image_entry_point = __cpu_to_le32(f->image_entry_point); 520 | h10->load_address = __cpu_to_le32(f->load_address); 521 | h10->image_checksum = __cpu_to_le32(crc); 522 | break; 523 | 524 | case HEADER_VERSION_V20: 525 | case HEADER_VERSION_V22: 526 | extension_length = sizeof(*h2x) - offsetof(typeof(*h2x), extension_header_type); 527 | h2x->magic_number = __cpu_to_be32(HEADER_MAGIC); 528 | h2x->version_number = __cpu_to_le32(f->version_number); 529 | h2x->header_version = __cpu_to_le32(f->soc->header_version); 530 | h2x->binary_type = __cpu_to_le32(f->soc->binary_type); 531 | h2x->extension_flags = __cpu_to_le32(PADDING_HEADER_FLAG); 532 | h2x->post_headers_length = __cpu_to_le32(extension_length); 533 | h2x->extension_header_type = __cpu_to_be32(PADDING_HEADER_MAGIC); 534 | h2x->extension_header_length = __cpu_to_le32(extension_length); 535 | h2x->image_length = __cpu_to_le32(f->image_length); 536 | h2x->image_entry_point = __cpu_to_le32(f->image_entry_point); 537 | h2x->load_address = __cpu_to_le32(f->load_address); 538 | h2x->image_checksum = __cpu_to_le32(crc); 539 | break; 540 | 541 | case HEADER_VERSION_V23: 542 | default: 543 | extension_length = sizeof(*h23) - offsetof(typeof(*h23), extension_header_type); 544 | h23->magic_number = __cpu_to_be32(HEADER_MAGIC); 545 | h23->version_number = __cpu_to_le32(f->version_number); 546 | h23->header_version = __cpu_to_le32(f->soc->header_version); 547 | h23->binary_type = __cpu_to_le32(f->soc->binary_type); 548 | h23->extension_flags = __cpu_to_le32(PADDING_HEADER_FLAG); 549 | h23->post_headers_length = __cpu_to_le32(extension_length); 550 | h23->extension_header_type = __cpu_to_be32(PADDING_HEADER_MAGIC); 551 | h23->extension_header_length = __cpu_to_le32(extension_length); 552 | h23->image_length = __cpu_to_le32(f->image_length); 553 | h23->image_entry_point = __cpu_to_le32(f->image_entry_point); 554 | h23->load_address = __cpu_to_le32(f->load_address); 555 | h23->image_checksum = __cpu_to_le32(crc); 556 | break; 557 | } 558 | 559 | return 0; 560 | } 561 | 562 | static int stm32image_open_source_file(const char *srcname, int force, struct stm32_file *src) 563 | { 564 | uint32_t src_hdr_length, src_data_length; 565 | struct stat sbuf; 566 | 567 | src->fd = open(srcname, O_RDONLY); 568 | if (src->fd == -1) { 569 | LOG_ERROR("Can't open %s: %s\n", srcname, strerror(errno)); 570 | return -1; 571 | } 572 | 573 | if (fstat(src->fd, &sbuf) < 0) { 574 | return -1; 575 | } 576 | 577 | src->file_size = sbuf.st_size; 578 | if ((sbuf.st_mode & S_IFBLK) && (ioctl(src->fd, BLKGETSIZE64, &src->file_size) < 0)) { 579 | LOG_ERROR("Can't read size of %s\n", srcname); 580 | return -1; 581 | } 582 | 583 | src->p = mmap(NULL, src->file_size, PROT_READ, MAP_SHARED, src->fd, 0); 584 | if (src->p == MAP_FAILED) { 585 | LOG_ERROR("Can't read %s\n", srcname); 586 | return -1; 587 | } 588 | 589 | if (stm32image_check_hdr(src, src->file_size) < 0) { 590 | LOG_ERROR("Not a valid image file %s\n", srcname); 591 | return -1; 592 | } 593 | 594 | if (!src->soc->wrapper_size) { 595 | LOG_ERROR("Image \"%s\" not supported yet\n", src->soc->name); 596 | return -1; 597 | } 598 | 599 | src_hdr_length = src->file_header_length; 600 | src_data_length = src->image_length; 601 | 602 | if (src_hdr_length + src_data_length < src->file_size) 603 | LOG_INFO("Strip extra padding from input file\n"); 604 | 605 | if (force == 0 && stm32image_check_wrapper(src) < 0) { 606 | LOG_ERROR("Wrapper already present in image file %s\n" 607 | "Use flag \"-f\" to force re-adding the wrapper\n", 608 | srcname); 609 | return -1; 610 | } 611 | 612 | if (src->is_encrypted) { 613 | LOG_ERROR("Image %s is encrypted. Unable to extract the content.\n", 614 | srcname); 615 | return -1; 616 | } 617 | 618 | return 0; 619 | } 620 | 621 | static int stm32image_close_source_file(struct stm32_file *src) 622 | { 623 | munmap(src->p, src->file_size); 624 | close(src->fd); 625 | 626 | return 0; 627 | } 628 | 629 | static int stm32image_dummy_source(struct stm32_file *src, const struct stm32_soc *soc) 630 | { 631 | unsigned int header_length; 632 | 633 | switch (soc->header_version) { 634 | case HEADER_VERSION_V10: 635 | header_length = sizeof(struct stm32_header_v10); 636 | break; 637 | 638 | case HEADER_VERSION_V20: 639 | case HEADER_VERSION_V22: 640 | header_length = sizeof(struct stm32_header_v2x); 641 | break; 642 | 643 | case HEADER_VERSION_V23: 644 | default: 645 | header_length = sizeof(struct stm32_header_v23); 646 | break; 647 | }; 648 | 649 | src->p = soc->dummy_fw - header_length; 650 | src->soc = soc; 651 | src->file_header_length = header_length; 652 | src->image_length = STM32_DUMMY_FW_LENGTH; 653 | src->load_address = soc->mem_start; 654 | src->version_number = 0; 655 | src->is_signed = false; 656 | src->is_encrypted = false; 657 | 658 | if (soc->binary_type == BIN_TYPE_CM33_IMAGE) { 659 | uint32_t *fw = (uint32_t *)soc->dummy_fw; 660 | 661 | src->image_entry_point = soc->mem_start + __le32_to_cpu(fw[1]); 662 | 663 | fw[0] = __cpu_to_le32(soc->mem_start + __le32_to_cpu(fw[0])); // SP 664 | fw[1] = __cpu_to_le32(src->image_entry_point); // reset 665 | } else { 666 | src->image_entry_point = soc->mem_start + (soc->wrapper_is_arm_thumb ? 1 : 0); 667 | } 668 | 669 | return 0; 670 | } 671 | 672 | static int stm32image_create_dest_file(const char *destname, int wrapper_before, 673 | const struct stm32_file *src) 674 | { 675 | struct stm32_file dst = { NULL, }; 676 | uint32_t src_hdr_length, dest_hdr_length; 677 | unsigned char *src_data; 678 | uint32_t src_data_length, jmp_add, padding, wrp_loadaddr, wrp_size; 679 | uint32_t new_loadaddr, new_entry = 0; 680 | uint32_t loadaddr, entry; 681 | 682 | src_hdr_length = src->file_header_length; 683 | src_data = ((uint8_t *)src->p) + src_hdr_length; 684 | src_data_length = src->image_length; 685 | 686 | entry = src->image_entry_point; 687 | loadaddr = src->load_address; 688 | 689 | dst.fd = open(destname, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0666); 690 | if (dst.fd == -1) { 691 | LOG_ERROR("Can't open %s: %s\n", destname, strerror(errno)); 692 | return -1; 693 | } 694 | 695 | dest_hdr_length = src_hdr_length; 696 | 697 | if (write(dst.fd, zero_buffer, dest_hdr_length) != dest_hdr_length) { 698 | LOG_ERROR("Write error %s: %s\n", destname, strerror(errno)); 699 | return -1; 700 | } 701 | 702 | wrp_size = src->soc->wrapper_size + sizeof(jmp_add); 703 | if (wrapper_before == 1) { 704 | wrp_loadaddr = ALIGN_DOWN(loadaddr - wrp_size, 705 | WRAPPER_ALIGNMENT); 706 | padding = loadaddr - (wrp_loadaddr + wrp_size); 707 | new_loadaddr = wrp_loadaddr; 708 | } else { 709 | wrp_loadaddr = ALIGN(loadaddr + src_data_length, WRAPPER_ALIGNMENT); 710 | padding = wrp_loadaddr - (loadaddr + src_data_length); 711 | new_loadaddr = loadaddr; 712 | } 713 | 714 | new_entry = (src->soc->wrapper_is_arm_thumb) ? ARM_THUMB_ADDRESS(wrp_loadaddr) : wrp_loadaddr; 715 | 716 | jmp_add = __cpu_to_le32(entry); 717 | 718 | if (wrapper_before == 1) { 719 | if (write(dst.fd, src->soc->wrapper, src->soc->wrapper_size) != src->soc->wrapper_size) { 720 | LOG_ERROR("Write error on %s: %s\n", destname, strerror(errno)); 721 | return -1; 722 | } 723 | 724 | if (write(dst.fd, &jmp_add, sizeof(jmp_add)) != 725 | sizeof(jmp_add)) { 726 | LOG_ERROR("Write error %s: %s\n", destname, strerror(errno)); 727 | return -1; 728 | } 729 | 730 | if (write(dst.fd, zero_buffer, padding) != padding) { 731 | LOG_ERROR("Write error %s: %s\n", destname, strerror(errno)); 732 | return -1; 733 | } 734 | } 735 | 736 | if (write(dst.fd, src_data, src_data_length) != src_data_length) { 737 | LOG_ERROR("Write error on %s: %s\n", destname, strerror(errno)); 738 | return -1; 739 | } 740 | 741 | if (wrapper_before == 0) { 742 | if (write(dst.fd, zero_buffer, padding) != padding) { 743 | LOG_ERROR("Write error %s: %s\n", destname, strerror(errno)); 744 | return -1; 745 | } 746 | 747 | if (write(dst.fd, src->soc->wrapper, src->soc->wrapper_size) != src->soc->wrapper_size) { 748 | LOG_ERROR("Write error on %s: %s\n", destname, strerror(errno)); 749 | return -1; 750 | } 751 | 752 | if (write(dst.fd, &jmp_add, sizeof(jmp_add)) != 753 | sizeof(jmp_add)) { 754 | LOG_ERROR("Write error on %s: %s\n", destname, strerror(errno)); 755 | return -1; 756 | } 757 | } 758 | 759 | dst.file_size = dest_hdr_length + wrp_size + padding + src_data_length; 760 | 761 | dst.p = mmap(0, dst.file_size, PROT_READ | PROT_WRITE, MAP_SHARED, 762 | dst.fd, 0); 763 | 764 | if (dst.p == MAP_FAILED) { 765 | LOG_ERROR("Can't write %s\n", destname); 766 | return -1; 767 | } 768 | dst.soc = src->soc; 769 | dst.file_header_length = dest_hdr_length; 770 | dst.version_number = src->version_number; 771 | dst.image_length = wrp_size + padding + src_data_length; 772 | dst.image_entry_point = new_entry; 773 | dst.load_address = new_loadaddr; 774 | 775 | stm32image_update_header(&dst); 776 | 777 | stm32image_print_header(&dst); 778 | LOG_INFO("Halt Address : 0x%08x\n", jmp_add); 779 | 780 | if (src->is_signed) 781 | LOG_INFO("\nATTENTION:\n\tSource file was \"signed\"!\n" 782 | "\tYou would need to sign the destination file \"%s\"\n", 783 | destname); 784 | 785 | munmap(dst.p, dst.file_size); 786 | close(dst.fd); 787 | return 0; 788 | } 789 | 790 | int main(int argc, char *argv[]) 791 | { 792 | int opt, err, wrapper_before = 0, force = 0; 793 | char *dstname = NULL, *srcname = NULL; 794 | struct stm32_file src = { NULL, }; 795 | 796 | while ((opt = getopt(argc, argv, "bfs:d:vVh")) != -1) { 797 | switch (opt) { 798 | case 'b': 799 | wrapper_before = 1; 800 | break; 801 | case 'f': 802 | force = 1; 803 | break; 804 | case 's': 805 | srcname = optarg; 806 | break; 807 | case 'd': 808 | dstname = optarg; 809 | break; 810 | case 'v': 811 | verbose = true; 812 | break; 813 | case 'V': 814 | LOG_ERROR("stm32wrapper4dbg version " VERSION "\n"); 815 | return 0; 816 | case 'h': 817 | default: 818 | LOG_ERROR( 819 | "Usage: %1$s -s srcfile -d destfile [-b] [-f]\n" 820 | " %1$s -V\n" 821 | " %1$s -h\n" 822 | " Add a debug wrapper to a stm32 image.\n" 823 | " If \"-b\" is not specified, the wrapper would be placed\n" 824 | " after the last byte of the image.\n" 825 | "\nOptions:\n" 826 | " -s srcfile input image in stm32 file format\n" 827 | " -d destfile output image in stm32 file format\n" 828 | " -b place the wrapper before the image\n" 829 | " -f force re-adding the wrapper\n" 830 | " -v verbose log\n" 831 | " -V display tool version and quit\n" 832 | " -h display this help and quit\n" 833 | "\nSpecial srcfile values:\n", 834 | argv[0]); 835 | for (unsigned int i = 0; i < ARRAY_SIZE(stm32_socs); i++) 836 | LOG_ERROR("%c \"%s\"", i ? ',' : ' ', stm32_socs[i].dummy_name); 837 | LOG_ERROR("\n"); 838 | return -1; 839 | } 840 | } 841 | 842 | if (!srcname) { 843 | LOG_ERROR("Missing -s option\n"); 844 | return -1; 845 | } 846 | 847 | if (!dstname) { 848 | LOG_ERROR("Missing -d option\n"); 849 | return -1; 850 | } 851 | 852 | /* check for dummy source file (infinite loop firmware) */ 853 | for (unsigned int i = 0; i < ARRAY_SIZE(stm32_socs); i++) { 854 | if (strcmp(srcname, stm32_socs[i].dummy_name)) 855 | continue; 856 | 857 | stm32image_dummy_source(&src, &stm32_socs[i]); 858 | 859 | return stm32image_create_dest_file(dstname, wrapper_before, &src); 860 | } 861 | 862 | /* continue with real source file */ 863 | err = stm32image_open_source_file(srcname, force, &src); 864 | if (err) 865 | return err; 866 | 867 | err = stm32image_create_dest_file(dstname, wrapper_before, &src); 868 | 869 | stm32image_close_source_file(&src); 870 | 871 | return err; 872 | } 873 | -------------------------------------------------------------------------------- /wrapper_stm32mp13x_ca7.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ 2 | /* 3 | * Copyright (c) 2019-2024, STMicroelectronics - All Rights Reserved 4 | * Author: Antonio Borneo 5 | */ 6 | 7 | #define RCC_DBGCFGR_OFFSET 0x468 8 | 9 | #include "wrapper_stm32mp15x_ca7.c" 10 | 11 | // vi:nospell 12 | -------------------------------------------------------------------------------- /wrapper_stm32mp13x_ca7.inc: -------------------------------------------------------------------------------- 1 | /* Generated automatically by Makefile */ 2 | 0x25,0x4b,0x40,0xf2,0x7f,0x42,0x25,0x4e,0x4f,0xf0,0x40,0x0c,0x5a,0x61,0x4f,0xf0, 3 | 0xa0,0x43,0xdf,0xf8,0x8c,0x90,0xd3,0xf8,0x68,0x24,0x55,0xec,0x0e,0x4f,0x42,0xf4, 4 | 0x80,0x72,0xc3,0xf8,0x68,0x24,0xd3,0xf8,0x68,0x34,0x04,0x23,0x73,0x60,0x1e,0xee, 5 | 0x10,0x3f,0x5b,0x09,0x19,0x19,0x45,0xf1,0x00,0x08,0xd9,0xf8,0x14,0x20,0xbc,0xf1, 6 | 0x00,0x0f,0x02,0xd0,0x74,0x68,0x04,0x2c,0x0c,0xd0,0x15,0x4b,0x42,0xf4,0x00,0x52, 7 | 0x5a,0x61,0x07,0x23,0x10,0xee,0x11,0x2e,0x52,0x04,0x73,0x60,0x11,0x4b,0x11,0xd4, 8 | 0x18,0x47,0xfe,0xe7,0x55,0xec,0x0e,0x4f,0xa1,0x42,0x78,0xeb,0x05,0x04,0xe6,0xd2, 9 | 0x59,0x18,0x82,0xf4,0x00,0x52,0x48,0xf1,0x00,0x08,0x0c,0xf1,0xff,0x3c,0xc9,0xf8, 10 | 0x14,0x20,0xdc,0xe7,0x23,0xf0,0x03,0x02,0x00,0xee,0x90,0x2e,0x40,0xf2,0xe7,0x12, 11 | 0x00,0xee,0xb0,0x2e,0xe4,0xe7,0x00,0xbf,0x00,0x50,0x00,0x5c,0x00,0x10,0x08,0x50, 12 | 0x00,0x20,0x00,0x50, 13 | -------------------------------------------------------------------------------- /wrapper_stm32mp15x_ca7.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ 2 | /* 3 | * Copyright (c) 2019-2024, STMicroelectronics - All Rights Reserved 4 | * Author: Antonio Borneo 5 | */ 6 | 7 | /* 8 | * ARM: https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/arm/aout.h 9 | * arm-none-eabi-gcc -Os -fcall-used-r4 -fcall-used-r5 -ffixed-r7 -ffixed-r11 -ffixed-r14 -fconserve-stack -c x.c -Wstack-usage=0 10 | * arm-none-eabi-gcc -Os -fcall-used-r4 -fcall-used-r5 -ffixed-r7 -ffixed-r11 -ffixed-r14 -fconserve-stack -fomit-frame-pointer -mcpu=cortex-m33 -mthumb -c x.c -Wstack-usage=0 11 | * arm-none-eabi-objdump -d x.o 12 | * 13 | * 0, 1, 2, 3, 4, 5, 6, X, 14 | * 8, 9, 10, X, 12, X, X, X, 15 | * 16 | * #define ARM_HARD_FRAME_POINTER_REGNUM 11 17 | * #define THUMB_HARD_FRAME_POINTER_REGNUM 7 18 | * 19 | * "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 20 | * "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc", 21 | * 22 | * https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/arm/arm.h 23 | * Register allocation in ARM Procedure Call Standard 24 | * (S - saved over call, F - Frame-related). 25 | * 26 | * r0 * argument word/integer result 27 | * r1-r3 argument word 28 | * 29 | * r4-r8 S register variable 30 | * r9 S (rfp) register variable (real frame pointer) 31 | * 32 | * r10 F S (sl) stack limit (used by -mapcs-stack-check) 33 | * r11 F S (fp) argument pointer 34 | * r12 (ip) temp workspace 35 | * r13 F S (sp) lower end of current stack frame 36 | * r14 (lr) link address/workspace 37 | * r15 F (pc) program counter 38 | * 39 | * 40 | * AARCH64: https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/aarch64/aarch64.h 41 | * aarch64-linux-gnu-gcc -Os -Wall -Wstack-usage=0 -mcpu=cortex-a35 -fcall-used-x19 -fcall-used-x20 -fcall-used-x21 -fcall-used-x22 -fcall-used-x23 -fcall-used-x24 -fcall-used-x25 \ 42 | * -fcall-used-x26 -fcall-used-x27 -fcall-used-x28 -fconserve-stack -fomit-frame-pointer -ffixed-x30 -c x.c 43 | * aarch64-linux-gnu-objdump -d firmware-example.o 44 | * 45 | * "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 46 | * "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 47 | * "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 48 | * "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp", 49 | * 50 | * 31 64-bit general purpose registers R0-R30: 51 | * R30 LR (link register) 52 | * R29 FP (frame pointer) 53 | * R19-R28 Callee-saved registers 54 | * R18 The platform register; use as temporary register. 55 | * R17 IP1 The second intra-procedure-call temporary register 56 | * (can be used by call veneers and PLT code); otherwise use 57 | * as a temporary register 58 | * R16 IP0 The first intra-procedure-call temporary register (can 59 | * be used by call veneers and PLT code); otherwise use as a 60 | * temporary register 61 | * R9-R15 Temporary registers 62 | * R8 Structure value parameter / temporary register 63 | * R0-R7 Parameter/result registers 64 | * 65 | * SP stack pointer, encoded as X/R31 where permitted. 66 | * ZR zero register, encoded as X/R31 elsewhere 67 | * 68 | * 32 x 128-bit floating-point/vector registers 69 | * V16-V31 Caller-saved (temporary) registers 70 | * V8-V15 Callee-saved registers 71 | * V0-V7 Parameter/result registers 72 | * 73 | * The vector register V0 holds scalar B0, H0, S0 and D0 in its least 74 | * significant bits. Unlike AArch32 S1 is not packed into D0, etc. 75 | * 76 | * P0-P7 Predicate low registers: valid in all predicate contexts 77 | * P8-P15 Predicate high registers: used as scratch space 78 | * 79 | * FFR First Fault Register, a fixed-use SVE predicate register 80 | * FFRT FFR token: a fake register used for modelling dependencies 81 | * 82 | * VG Pseudo "vector granules" register 83 | * 84 | * VG is the number of 64-bit elements in an SVE vector. We define 85 | * it as a hard register so that we can easily map it to the DWARF VG 86 | * register. GCC internally uses the poly_int variable aarch64_sve_vg 87 | * instead. 88 | */ 89 | 90 | #include 91 | 92 | #define BIT(x) (1UL << (x)) 93 | 94 | #define DBGDSCR_HDBGEN_MASK BIT(14) 95 | #define DBGBCR0_VAL (BIT(8) | BIT(7) | BIT(6) | BIT(5) | BIT(2) | BIT(1) | BIT(0)) 96 | //#define DBGBCR0_VAL 0x000001e0 97 | #define DBGBVR_MASK (~(BIT(0) | BIT(1))) 98 | 99 | 100 | #define CNT_RELOADS_PER_S 32 101 | #define DELAY_S 2 102 | #define CNT_RELOADS (DELAY_S * CNT_RELOADS_PER_S) 103 | 104 | #define BSEC_BASE 0x5c005000 105 | #define BSEC_DENR_OFFSET 0x014 106 | #define BSEC_DENR_VAL 0x0000047f 107 | 108 | #define RCC_BASE 0x50000000 109 | #ifndef RCC_DBGCFGR_OFFSET 110 | #define RCC_DBGCFGR_OFFSET 0x80c 111 | #endif 112 | #define RCC_DBGCFGR_DBGEN BIT(8) 113 | 114 | #define DBGMCU_BASE 0x50081000 115 | #define DBGMCU_CR_OFFSET 0x004 116 | #define DBGMCU_CR_VAL1 0x00000004 117 | #define DBGMCU_CR_VAL2 0x00000007 118 | 119 | /* Bootfail red LED on PA13 */ 120 | #define LED_GPIO_BASE 0x50002000 121 | #define LED_GPIO_ODR_OFFSET 0x014 122 | #define LED_GPIO_MASK BIT(13) 123 | 124 | static inline void write32(unsigned long addr, uint32_t val) 125 | { 126 | volatile uint32_t *a = (uint32_t *)addr; 127 | 128 | *a = val; 129 | } 130 | 131 | static inline uint32_t read32(unsigned long addr) 132 | { 133 | volatile uint32_t *a = (uint32_t *)addr; 134 | 135 | return *a; 136 | } 137 | 138 | static inline void setbits32(unsigned long addr, uint32_t val) 139 | { 140 | volatile uint32_t *a = (uint32_t *)addr; 141 | 142 | *a = *a | val; 143 | } 144 | 145 | static inline void clrbits32(unsigned long addr, uint32_t val) 146 | { 147 | volatile uint32_t *a = (uint32_t *)addr; 148 | 149 | *a = *a & ~val; 150 | } 151 | 152 | void _start(int a, int b, int c, int d) __attribute__ ((noreturn)); 153 | void _start(int a, int b, int c, int d) 154 | { 155 | #ifdef __GCC_HAVE_DWARF2_CFI_ASM 156 | asm(".cfi_undefined lr"); 157 | asm(".cfi_undefined sp"); 158 | #endif 159 | 160 | /* Only r0 is set by the bootrom */ 161 | register int r0 asm ("r0") = a; 162 | 163 | uint32_t loc_fsbl_ptr; 164 | uint32_t dbgdscr; 165 | 166 | /* open debug early, as DBGSWEN is required to access DBGMCU */ 167 | write32(BSEC_BASE + BSEC_DENR_OFFSET, BSEC_DENR_VAL); 168 | 169 | setbits32(RCC_BASE + RCC_DBGCFGR_OFFSET, RCC_DBGCFGR_DBGEN); 170 | (void)read32(RCC_BASE + RCC_DBGCFGR_OFFSET); 171 | 172 | /* signal the debugger that there is a wrapper */ 173 | write32(DBGMCU_BASE + DBGMCU_CR_OFFSET, DBGMCU_CR_VAL1); 174 | 175 | uint32_t cnt_frq; 176 | asm("mrc p15, 0, %0, c14, c0, 0" : "=r" (cnt_frq)); 177 | 178 | uint32_t delta = cnt_frq / CNT_RELOADS_PER_S; 179 | uint64_t cnt, next_cnt; 180 | asm("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cnt)); 181 | next_cnt = cnt + delta; 182 | 183 | /* wait for debugger or timeout, blinking the LED */ 184 | uint32_t led = read32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET); 185 | for (unsigned int timeout = CNT_RELOADS; timeout; ) { 186 | if (read32(DBGMCU_BASE + DBGMCU_CR_OFFSET) != DBGMCU_CR_VAL1) 187 | break; 188 | 189 | asm volatile ("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cnt)); 190 | if (cnt > next_cnt) { 191 | led ^= LED_GPIO_MASK; 192 | write32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET, led); 193 | next_cnt += delta; 194 | timeout--; 195 | } 196 | } 197 | 198 | /* LED off */ 199 | write32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET, led | LED_GPIO_MASK); 200 | 201 | /* final value in DBGMCU_CR */ 202 | write32(DBGMCU_BASE + DBGMCU_CR_OFFSET, DBGMCU_CR_VAL2); 203 | 204 | asm("ldr %0, fsbl_ptr" : "=r" (loc_fsbl_ptr)); 205 | 206 | /* does debugger ask to halt? */ 207 | asm("mrc p14, 0, %0, c0, c1, 0" : "=r" (dbgdscr)); 208 | if (dbgdscr & DBGDSCR_HDBGEN_MASK) { 209 | /* set HW breakpoint at FSBL-A */ 210 | asm("mcr p14, 0, %0, c0, c0, 4" : : "r" (loc_fsbl_ptr & DBGBVR_MASK)); /* dbgbvr0 */ 211 | asm("mcr p14, 0, %0, c0, c0, 5" : : "r" (DBGBCR0_VAL)); 212 | } 213 | 214 | /* at last, jump to FSBL-A */ 215 | asm("bx %0" : : "r" (loc_fsbl_ptr), "r" (r0)); 216 | 217 | /* validate attribute noreturn */ 218 | while (1) {}; 219 | } 220 | 221 | // vi:nospell 222 | -------------------------------------------------------------------------------- /wrapper_stm32mp15x_ca7.inc: -------------------------------------------------------------------------------- 1 | /* Generated automatically by Makefile */ 2 | 0x25,0x4b,0x40,0xf2,0x7f,0x42,0x25,0x4e,0x4f,0xf0,0x40,0x0c,0x5a,0x61,0x4f,0xf0, 3 | 0xa0,0x43,0xdf,0xf8,0x8c,0x90,0xd3,0xf8,0x0c,0x28,0x55,0xec,0x0e,0x4f,0x42,0xf4, 4 | 0x80,0x72,0xc3,0xf8,0x0c,0x28,0xd3,0xf8,0x0c,0x38,0x04,0x23,0x73,0x60,0x1e,0xee, 5 | 0x10,0x3f,0x5b,0x09,0x19,0x19,0x45,0xf1,0x00,0x08,0xd9,0xf8,0x14,0x20,0xbc,0xf1, 6 | 0x00,0x0f,0x02,0xd0,0x74,0x68,0x04,0x2c,0x0c,0xd0,0x15,0x4b,0x42,0xf4,0x00,0x52, 7 | 0x5a,0x61,0x07,0x23,0x10,0xee,0x11,0x2e,0x52,0x04,0x73,0x60,0x11,0x4b,0x11,0xd4, 8 | 0x18,0x47,0xfe,0xe7,0x55,0xec,0x0e,0x4f,0xa1,0x42,0x78,0xeb,0x05,0x04,0xe6,0xd2, 9 | 0x59,0x18,0x82,0xf4,0x00,0x52,0x48,0xf1,0x00,0x08,0x0c,0xf1,0xff,0x3c,0xc9,0xf8, 10 | 0x14,0x20,0xdc,0xe7,0x23,0xf0,0x03,0x02,0x00,0xee,0x90,0x2e,0x40,0xf2,0xe7,0x12, 11 | 0x00,0xee,0xb0,0x2e,0xe4,0xe7,0x00,0xbf,0x00,0x50,0x00,0x5c,0x00,0x10,0x08,0x50, 12 | 0x00,0x20,0x00,0x50, 13 | -------------------------------------------------------------------------------- /wrapper_stm32mp21x_ca35.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ 2 | /* 3 | * Copyright (c) 2019-2024, STMicroelectronics - All Rights Reserved 4 | * Author: Antonio Borneo 5 | */ 6 | 7 | /* 8 | * ARM: https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/arm/aout.h 9 | * arm-none-eabi-gcc -Os -fcall-used-r4 -fcall-used-r5 -ffixed-r7 -ffixed-r11 -ffixed-r14 -fconserve-stack -c x.c -Wstack-usage=0 10 | * arm-none-eabi-gcc -Os -fcall-used-r4 -fcall-used-r5 -ffixed-r7 -ffixed-r11 -ffixed-r14 -fconserve-stack -fomit-frame-pointer -mcpu=cortex-m33 -mthumb -c x.c -Wstack-usage=0 11 | * arm-none-eabi-objdump -d x.o 12 | * 13 | * 0, 1, 2, 3, 4, 5, 6, X, 14 | * 8, 9, 10, X, 12, X, X, X, 15 | * 16 | * #define ARM_HARD_FRAME_POINTER_REGNUM 11 17 | * #define THUMB_HARD_FRAME_POINTER_REGNUM 7 18 | * 19 | * "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 20 | * "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc", 21 | * 22 | * https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/arm/arm.h 23 | * Register allocation in ARM Procedure Call Standard 24 | * (S - saved over call, F - Frame-related). 25 | * 26 | * r0 * argument word/integer result 27 | * r1-r3 argument word 28 | * 29 | * r4-r8 S register variable 30 | * r9 S (rfp) register variable (real frame pointer) 31 | * 32 | * r10 F S (sl) stack limit (used by -mapcs-stack-check) 33 | * r11 F S (fp) argument pointer 34 | * r12 (ip) temp workspace 35 | * r13 F S (sp) lower end of current stack frame 36 | * r14 (lr) link address/workspace 37 | * r15 F (pc) program counter 38 | * 39 | * 40 | * AARCH64: https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/aarch64/aarch64.h 41 | * aarch64-linux-gnu-gcc -Os -Wall -Wstack-usage=0 -mcpu=cortex-a35 -fcall-used-x19 -fcall-used-x20 -fcall-used-x21 -fcall-used-x22 -fcall-used-x23 -fcall-used-x24 -fcall-used-x25 \ 42 | * -fcall-used-x26 -fcall-used-x27 -fcall-used-x28 -fconserve-stack -fomit-frame-pointer -ffixed-x30 -c x.c 43 | * aarch64-linux-gnu-objdump -d firmware-example.o 44 | * 45 | * "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 46 | * "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 47 | * "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 48 | * "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp", 49 | * 50 | * 31 64-bit general purpose registers R0-R30: 51 | * R30 LR (link register) 52 | * R29 FP (frame pointer) 53 | * R19-R28 Callee-saved registers 54 | * R18 The platform register; use as temporary register. 55 | * R17 IP1 The second intra-procedure-call temporary register 56 | * (can be used by call veneers and PLT code); otherwise use 57 | * as a temporary register 58 | * R16 IP0 The first intra-procedure-call temporary register (can 59 | * be used by call veneers and PLT code); otherwise use as a 60 | * temporary register 61 | * R9-R15 Temporary registers 62 | * R8 Structure value parameter / temporary register 63 | * R0-R7 Parameter/result registers 64 | * 65 | * SP stack pointer, encoded as X/R31 where permitted. 66 | * ZR zero register, encoded as X/R31 elsewhere 67 | * 68 | * 32 x 128-bit floating-point/vector registers 69 | * V16-V31 Caller-saved (temporary) registers 70 | * V8-V15 Callee-saved registers 71 | * V0-V7 Parameter/result registers 72 | * 73 | * The vector register V0 holds scalar B0, H0, S0 and D0 in its least 74 | * significant bits. Unlike AArch32 S1 is not packed into D0, etc. 75 | * 76 | * P0-P7 Predicate low registers: valid in all predicate contexts 77 | * P8-P15 Predicate high registers: used as scratch space 78 | * 79 | * FFR First Fault Register, a fixed-use SVE predicate register 80 | * FFRT FFR token: a fake register used for modelling dependencies 81 | * 82 | * VG Pseudo "vector granules" register 83 | * 84 | * VG is the number of 64-bit elements in an SVE vector. We define 85 | * it as a hard register so that we can easily map it to the DWARF VG 86 | * register. GCC internally uses the poly_int variable aarch64_sve_vg 87 | * instead. 88 | */ 89 | 90 | #include 91 | 92 | #define BIT(x) (1UL << (x)) 93 | 94 | /* compute SECDED ECC as HAMMING(17,12) with parity */ 95 | #define PARITY_4BIT(x) ((((x) >> 3) ^ ((x) >> 2) ^ ((x) >> 1) ^ (x)) & 1) 96 | #define PARITY_12BIT(x) PARITY_4BIT(((x) >> 8) ^ ((x) >> 4) ^ (x)) 97 | #define BSEC_DENR_ECC(x) (((PARITY_12BIT((x) & 0x800)) << 17) | \ 98 | ((PARITY_12BIT((x) & 0x7f0)) << 16) | \ 99 | ((PARITY_12BIT((x) & 0x78e)) << 15) | \ 100 | ((PARITY_12BIT((x) & 0x66d)) << 14) | \ 101 | ((PARITY_12BIT((x) & 0xd5b)) << 13) | \ 102 | ((PARITY_12BIT((x) & 0xcb7)) << 12)) 103 | #define BSEC_DENR_v(x) (0xdeb00000 | BSEC_DENR_ECC(x) | ((x) & 0xfff)) 104 | 105 | #define MPIDR_CPUID_MASK 0x0000ffff 106 | #define EDSCR_HDE_MASK BIT(14) 107 | #define DBGBCR0_EL1_VAL (BIT(13) | BIT(8) | BIT(7) | BIT(6) | BIT(5) | BIT(2) | BIT(1) | BIT(0)) 108 | //#define DBGBCR0_EL1_VAL 0x000021e7 109 | 110 | #define CNT_RELOADS_PER_S 32 111 | #define DELAY_S 2 112 | #define CNT_RELOADS (DELAY_S * CNT_RELOADS_PER_S) 113 | 114 | #define BSEC_BASE 0x44000000 115 | #define BSEC_DENR_OFFSET 0xe20 116 | #define BSEC_DENR_VAL BSEC_DENR_v(0x0fff) 117 | #define BSEC_DBGACR_OFFSET 0x00000eac 118 | #define BSEC_DBGMCR_OFFSET 0x00000e8c 119 | #define BSEC_DBGXCR_ENABLE 0xb4b4b400 120 | #define BSEC_AP_UNLOCK_OFFSET 0x00000e90 121 | #define BSEC_AP_UNLOCK_ENABLE 0x000000b4 122 | 123 | #define RCC_BASE 0x44200000 124 | #define RCC_DBGCFGR_OFFSET 0x520 125 | #define RCC_DBGCFGR_DBGMCUEN BIT(10) 126 | 127 | #define DBGMCU_BASE 0x440a0000 128 | #define DBGMCU_CR_OFFSET 0x004 129 | #define DBGMCU_CR_VAL1 0x00000004 130 | #define DBGMCU_CR_VAL2 0x00000007 131 | #define DBGMCU_DBG_AUTH_DEV_OFFSET 0x00000104 132 | 133 | #define TDCID 1 134 | 135 | #define RIFSC_RIMC_BASE 0x42080000 136 | #define RIFSC_RIMC_CR_OFFSET 0xc00 137 | #define RIFSC_RIMC_CR_TDCID_SHIFT 4 138 | #define RIFSC_RIMC_CR_TDCID_MASK (7 << RIFSC_RIMC_CR_TDCID_SHIFT) 139 | #define RIFSC_RIMC_CR_TDCID_VALUE ((TDCID) << RIFSC_RIMC_CR_TDCID_SHIFT) 140 | 141 | /* Bootfail red LED on PH4 */ 142 | #define LED_GPIO_BASE 0x442b0000 143 | #define LED_GPIO_ODR_OFFSET 0x014 144 | #define LED_GPIO_MASK BIT(4) 145 | 146 | #define STGENC_BASE 0x48080000 147 | #define STGENC_CNTFID0_OFFSET 0x020 148 | 149 | static inline void write32(unsigned long addr, uint32_t val) 150 | { 151 | volatile uint32_t *a = (uint32_t *)addr; 152 | 153 | *a = val; 154 | } 155 | 156 | static inline uint32_t read32(unsigned long addr) 157 | { 158 | volatile uint32_t *a = (uint32_t *)addr; 159 | 160 | return *a; 161 | } 162 | 163 | static inline void setbits32(unsigned long addr, uint32_t val) 164 | { 165 | volatile uint32_t *a = (uint32_t *)addr; 166 | 167 | *a = *a | val; 168 | } 169 | 170 | static inline void clrbits32(unsigned long addr, uint32_t val) 171 | { 172 | volatile uint32_t *a = (uint32_t *)addr; 173 | 174 | *a = *a & ~val; 175 | } 176 | 177 | void _start(void) __attribute__ ((noreturn)); 178 | void _start(void) 179 | { 180 | #ifdef __GCC_HAVE_DWARF2_CFI_ASM 181 | asm(".cfi_undefined lr"); 182 | asm(".cfi_undefined sp"); 183 | #endif 184 | 185 | uint32_t loc_fsbl_ptr; 186 | uint32_t edscr; 187 | 188 | /* skip wrapper if not CM33-TD */ 189 | uint32_t rifsc_rimc_cr = read32(RIFSC_RIMC_BASE + RIFSC_RIMC_CR_OFFSET); 190 | if ((rifsc_rimc_cr & RIFSC_RIMC_CR_TDCID_MASK) != RIFSC_RIMC_CR_TDCID_VALUE) 191 | goto wrapper_exit; 192 | 193 | /* put secondary cores in pen-hold */ 194 | uint64_t mpidr_el1; 195 | asm("mrs %0, mpidr_el1" : "=r" (mpidr_el1)); 196 | if (mpidr_el1 & MPIDR_CPUID_MASK) { 197 | asm("wfe"); 198 | goto pen_hold_exit; 199 | } 200 | 201 | /* open debug early, as DBGSWEN is required to access DBGMCU */ 202 | write32(BSEC_BASE + BSEC_DENR_OFFSET, BSEC_DENR_VAL); 203 | 204 | write32(BSEC_BASE + BSEC_DBGACR_OFFSET, BSEC_DBGXCR_ENABLE); 205 | write32(BSEC_BASE + BSEC_DBGMCR_OFFSET, BSEC_DBGXCR_ENABLE); 206 | write32(BSEC_BASE + BSEC_AP_UNLOCK_OFFSET, BSEC_AP_UNLOCK_ENABLE); 207 | 208 | setbits32(RCC_BASE + RCC_DBGCFGR_OFFSET, RCC_DBGCFGR_DBGMCUEN); 209 | (void)read32(RCC_BASE + RCC_DBGCFGR_OFFSET); 210 | 211 | write32(DBGMCU_BASE + DBGMCU_DBG_AUTH_DEV_OFFSET, 0); 212 | 213 | /* Prevent CA35 to sleep and signal the debugger that there is a wrapper */ 214 | write32(DBGMCU_BASE + DBGMCU_CR_OFFSET, DBGMCU_CR_VAL1); 215 | 216 | /* 217 | * BootROM does not set cntfrq_el0. Use stgenc_cntfid0 value instead of 218 | * mrs x6, cntfrq_el0 219 | */ 220 | uint32_t delta = read32(STGENC_BASE + STGENC_CNTFID0_OFFSET) / CNT_RELOADS_PER_S; 221 | uint64_t cnt, next_cnt; 222 | asm("mrs %0, cntpct_el0" : "=r" (cnt)); 223 | next_cnt = cnt + delta; 224 | 225 | /* wait for debugger or timeout, blinking the LED */ 226 | uint32_t led = read32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET); 227 | for (unsigned int timeout = CNT_RELOADS; timeout; ) { 228 | if (read32(DBGMCU_BASE + DBGMCU_CR_OFFSET) != DBGMCU_CR_VAL1) 229 | break; 230 | 231 | asm volatile ("mrs %0, cntpct_el0" : "=r" (cnt)); 232 | if (cnt > next_cnt) { 233 | led ^= LED_GPIO_MASK; 234 | write32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET, led); 235 | next_cnt += delta; 236 | timeout--; 237 | } 238 | } 239 | 240 | /* LED off */ 241 | write32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET, led | LED_GPIO_MASK); 242 | 243 | /* final value in DBGMCU_CR */ 244 | write32(DBGMCU_BASE + DBGMCU_CR_OFFSET, DBGMCU_CR_VAL2); 245 | 246 | /* secondary cores out of pen-hold */ 247 | asm("sev"); 248 | 249 | pen_hold_exit: 250 | 251 | /* does debugger ask to halt? */ 252 | asm("mrs %0, mdscr_el1" : "=r" (edscr)); 253 | if (edscr & EDSCR_HDE_MASK) { 254 | /* set HW breakpoint at FSBL-A */ 255 | asm("ldr %w0, fsbl_ptr" : "=r" (loc_fsbl_ptr)); 256 | asm("msr dbgbvr0_el1, %0" : : "r" (loc_fsbl_ptr)); 257 | asm("msr dbgbcr0_el1, %0" : : "r" (DBGBCR0_EL1_VAL)); 258 | } 259 | 260 | wrapper_exit: 261 | 262 | asm("ldr %w0, fsbl_ptr" : "=r" (loc_fsbl_ptr)); 263 | 264 | /* at last, jump to FSBL-A */ 265 | asm("br %0" : : "r" (loc_fsbl_ptr)); 266 | 267 | /* validate attribute noreturn */ 268 | while (1) {}; 269 | } 270 | 271 | // vi:nospell 272 | -------------------------------------------------------------------------------- /wrapper_stm32mp21x_ca35.inc: -------------------------------------------------------------------------------- 1 | /* Generated automatically by Makefile */ 2 | 0x00,0x80,0x81,0xd2,0x00,0x41,0xa8,0xf2,0x00,0x00,0x40,0xb9,0x00,0x08,0x1c,0x12, 3 | 0x1f,0x40,0x00,0x71,0x61,0x01,0x00,0x54,0xa0,0x00,0x38,0xd5,0x1f,0x3c,0x00,0x72, 4 | 0x60,0x01,0x00,0x54,0x5f,0x20,0x03,0xd5,0x40,0x02,0x30,0xd5,0xa0,0x00,0x70,0x36, 5 | 0x20,0x08,0x00,0x18,0x80,0x00,0x10,0xd5,0xe0,0x3c,0x84,0xd2,0xa0,0x00,0x10,0xd5, 6 | 0xa0,0x07,0x00,0x18,0x00,0x00,0x1f,0xd6,0x00,0x00,0x00,0x14,0x00,0xc4,0x81,0xd2, 7 | 0x00,0x80,0xa8,0xf2,0xe1,0xff,0x99,0x52,0x61,0xd6,0xbb,0x72,0x01,0x00,0x00,0xb9, 8 | 0x81,0xd5,0x81,0xd2,0x01,0x80,0xa8,0xf2,0x00,0x80,0x96,0x52,0x80,0x96,0xb6,0x72, 9 | 0x20,0x00,0x00,0xb9,0x20,0x00,0x1e,0xb8,0x00,0xd2,0x81,0xd2,0x00,0x80,0xa8,0xf2, 10 | 0x81,0x16,0x80,0x52,0x01,0x00,0x00,0xb9,0x00,0xa4,0x80,0xd2,0x00,0x84,0xa8,0xf2, 11 | 0x83,0x00,0x80,0xd2,0x43,0x81,0xa8,0xf2,0x01,0x00,0x40,0xb9,0x85,0x02,0x80,0xd2, 12 | 0x65,0x85,0xa8,0xf2,0x21,0x00,0x16,0x32,0x01,0x00,0x00,0xb9,0x04,0x08,0x80,0x52, 13 | 0x00,0x00,0x40,0xb9,0x80,0x20,0x80,0xd2,0x40,0x81,0xa8,0xf2,0x1f,0x00,0x00,0xb9, 14 | 0x80,0x00,0x80,0x52,0x60,0x00,0x00,0xb9,0x00,0x04,0x80,0xd2,0x00,0x01,0xa9,0xf2, 15 | 0x02,0x00,0x40,0xb9,0xa1,0x00,0x40,0xb9,0x20,0xe0,0x3b,0xd5,0x42,0x7c,0x05,0x53, 16 | 0x40,0x00,0x00,0x8b,0x84,0x00,0x00,0x34,0x66,0x00,0x40,0xb9,0xdf,0x10,0x00,0x71, 17 | 0x20,0x01,0x00,0x54,0x80,0x02,0x80,0xd2,0x60,0x85,0xa8,0xf2,0x21,0x00,0x1c,0x32, 18 | 0x01,0x00,0x00,0xb9,0xe0,0x00,0x80,0x52,0x60,0x00,0x00,0xb9,0x9f,0x20,0x03,0xd5, 19 | 0xc6,0xff,0xff,0x17,0x26,0xe0,0x3b,0xd5,0x1f,0x00,0x06,0xeb,0x42,0xfe,0xff,0x54, 20 | 0x21,0x00,0x1c,0x52,0x00,0x00,0x02,0x8b,0x84,0x04,0x00,0x51,0xa1,0x00,0x00,0xb9, 21 | 0xed,0xff,0xff,0x17, 22 | -------------------------------------------------------------------------------- /wrapper_stm32mp21x_cm33.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ 2 | /* 3 | * Copyright (c) 2019-2024, STMicroelectronics - All Rights Reserved 4 | * Author: Antonio Borneo 5 | */ 6 | 7 | /* 8 | * ARM: https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/arm/aout.h 9 | * arm-none-eabi-gcc -Os -fcall-used-r4 -fcall-used-r5 -ffixed-r7 -ffixed-r11 -ffixed-r14 -fconserve-stack -c x.c -Wstack-usage=0 10 | * arm-none-eabi-gcc -Os -fcall-used-r4 -fcall-used-r5 -ffixed-r7 -ffixed-r11 -ffixed-r14 -fconserve-stack -fomit-frame-pointer -mcpu=cortex-m33 -mthumb -c x.c -Wstack-usage=0 11 | * arm-none-eabi-objdump -d x.o 12 | * 13 | * 0, 1, 2, 3, 4, 5, 6, X, 14 | * 8, 9, 10, X, 12, X, X, X, 15 | * 16 | * #define ARM_HARD_FRAME_POINTER_REGNUM 11 17 | * #define THUMB_HARD_FRAME_POINTER_REGNUM 7 18 | * 19 | * "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 20 | * "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc", 21 | * 22 | * https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/arm/arm.h 23 | * Register allocation in ARM Procedure Call Standard 24 | * (S - saved over call, F - Frame-related). 25 | * 26 | * r0 * argument word/integer result 27 | * r1-r3 argument word 28 | * 29 | * r4-r8 S register variable 30 | * r9 S (rfp) register variable (real frame pointer) 31 | * 32 | * r10 F S (sl) stack limit (used by -mapcs-stack-check) 33 | * r11 F S (fp) argument pointer 34 | * r12 (ip) temp workspace 35 | * r13 F S (sp) lower end of current stack frame 36 | * r14 (lr) link address/workspace 37 | * r15 F (pc) program counter 38 | * 39 | * 40 | * AARCH64: https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/aarch64/aarch64.h 41 | * aarch64-linux-gnu-gcc -Os -Wall -Wstack-usage=0 -mcpu=cortex-a35 -fcall-used-x19 -fcall-used-x20 -fcall-used-x21 -fcall-used-x22 -fcall-used-x23 -fcall-used-x24 -fcall-used-x25 \ 42 | * -fcall-used-x26 -fcall-used-x27 -fcall-used-x28 -fconserve-stack -fomit-frame-pointer -ffixed-x30 -c x.c 43 | * aarch64-linux-gnu-objdump -d firmware-example.o 44 | * 45 | * "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 46 | * "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 47 | * "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 48 | * "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp", 49 | * 50 | * 31 64-bit general purpose registers R0-R30: 51 | * R30 LR (link register) 52 | * R29 FP (frame pointer) 53 | * R19-R28 Callee-saved registers 54 | * R18 The platform register; use as temporary register. 55 | * R17 IP1 The second intra-procedure-call temporary register 56 | * (can be used by call veneers and PLT code); otherwise use 57 | * as a temporary register 58 | * R16 IP0 The first intra-procedure-call temporary register (can 59 | * be used by call veneers and PLT code); otherwise use as a 60 | * temporary register 61 | * R9-R15 Temporary registers 62 | * R8 Structure value parameter / temporary register 63 | * R0-R7 Parameter/result registers 64 | * 65 | * SP stack pointer, encoded as X/R31 where permitted. 66 | * ZR zero register, encoded as X/R31 elsewhere 67 | * 68 | * 32 x 128-bit floating-point/vector registers 69 | * V16-V31 Caller-saved (temporary) registers 70 | * V8-V15 Callee-saved registers 71 | * V0-V7 Parameter/result registers 72 | * 73 | * The vector register V0 holds scalar B0, H0, S0 and D0 in its least 74 | * significant bits. Unlike AArch32 S1 is not packed into D0, etc. 75 | * 76 | * P0-P7 Predicate low registers: valid in all predicate contexts 77 | * P8-P15 Predicate high registers: used as scratch space 78 | * 79 | * FFR First Fault Register, a fixed-use SVE predicate register 80 | * FFRT FFR token: a fake register used for modelling dependencies 81 | * 82 | * VG Pseudo "vector granules" register 83 | * 84 | * VG is the number of 64-bit elements in an SVE vector. We define 85 | * it as a hard register so that we can easily map it to the DWARF VG 86 | * register. GCC internally uses the poly_int variable aarch64_sve_vg 87 | * instead. 88 | */ 89 | 90 | #include 91 | 92 | #define BIT(x) (1UL << (x)) 93 | 94 | /* compute SECDED ECC as HAMMING(17,12) with parity */ 95 | #define PARITY_4BIT(x) ((((x) >> 3) ^ ((x) >> 2) ^ ((x) >> 1) ^ (x)) & 1) 96 | #define PARITY_12BIT(x) PARITY_4BIT(((x) >> 8) ^ ((x) >> 4) ^ (x)) 97 | #define BSEC_DENR_ECC(x) (((PARITY_12BIT((x) & 0x800)) << 17) | \ 98 | ((PARITY_12BIT((x) & 0x7f0)) << 16) | \ 99 | ((PARITY_12BIT((x) & 0x78e)) << 15) | \ 100 | ((PARITY_12BIT((x) & 0x66d)) << 14) | \ 101 | ((PARITY_12BIT((x) & 0xd5b)) << 13) | \ 102 | ((PARITY_12BIT((x) & 0xcb7)) << 12)) 103 | #define BSEC_DENR_v(x) (0xdeb00000 | BSEC_DENR_ECC(x) | ((x) & 0xfff)) 104 | 105 | #define CPU_FREQ_HZ 300000000 106 | #define CM33_SYST_FREQ_HZ CPU_FREQ_HZ 107 | #define CM33_SYST_RELOADS_PER_S 32 108 | #define CM33_SYST_RELOAD_VALUE ((CM33_SYST_FREQ_HZ) / (CM33_SYST_RELOADS_PER_S)) 109 | #define DELAY_S 2 110 | #define CM33_SYST_RELOADS (DELAY_S * CM33_SYST_RELOADS_PER_S) 111 | 112 | /* must fit in 24 bits */ 113 | #if CM33_SYST_RELOAD_VALUE > 0x00ffffff 114 | #error SYST out of range, increase CM33_SYST_RELOADS_PER_S 115 | #endif 116 | 117 | #define CM33_RESET_VECTOR 0x0e040000 118 | #define CM33_RESET_VECTOR_PC_OFFSET 0x004 119 | 120 | #define CM33_SYST_BASE 0xe000e010 121 | #define CM33_SYST_CSR_OFFSET 0x000 122 | #define CM33_SYST_RVR_OFFSET 0x004 123 | #define CM33_SYST_CVR_OFFSET 0x008 124 | #define CM33_SYST_CSR_ENABLE (BIT(2) | BIT(0)) 125 | #define CM33_SYST_CSR_CNTFLG_MASK BIT(16) 126 | 127 | #define CM33_FP_BASE 0xe0002000 128 | #define CM33_FP_CTRL_OFFSET 0x000 129 | #define CM33_FP_COMP_OFFSET(n) (0x008 + 4 * (n)) 130 | #define CM33_FP_CTRL_ENABLE (BIT(1) | BIT(0)) 131 | #define CM33_FP_COMP_ENABLE BIT(0) 132 | 133 | #define CM33_DHCSR_BASE 0xe000edf0 134 | #define CM33_DHCSR_C_DEBUGEN BIT(0) 135 | 136 | #define BSEC_BASE 0x44000000 137 | #define BSEC_SCRATCHR1_OFFSET 0xe04 138 | #define BSEC_SCRATCHR1_VAL 1 139 | #define BSEC_DENR_OFFSET 0xe20 140 | #define BSEC_DENR_VAL BSEC_DENR_v(0x0fff) 141 | #define BSEC_DBGACR_OFFSET 0x00000eac 142 | #define BSEC_DBGMCR_OFFSET 0x00000e8c 143 | #define BSEC_DBGXCR_ENABLE 0xb4b4b400 144 | #define BSEC_AP_UNLOCK_OFFSET 0x00000e90 145 | #define BSEC_AP_UNLOCK_ENABLE 0x000000b4 146 | 147 | #define RCC_BASE 0x44200000 148 | #define RCC_DBGCFGR_OFFSET 0x520 149 | #define RCC_DBGCFGR_DBGMCUEN BIT(10) 150 | #define RCC_DELAY_N 16 /* (N >= 5) */ 151 | 152 | #define DBGMCU_BASE 0x440a0000 153 | #define DBGMCU_CR_OFFSET 0x004 154 | #define DBGMCU_CR_VAL1 0x00000004 155 | #define DBGMCU_CR_VAL2 0x00000007 156 | #define DBGMCU_DBG_AUTH_DEV_OFFSET 0x00000104 157 | 158 | #define TDCID 2 159 | 160 | #define RIFSC_RIMC_BASE 0x42080000 161 | #define RIFSC_RIMC_CR_OFFSET 0xc00 162 | #define RIFSC_RIMC_CR_TDCID_SHIFT 4 163 | #define RIFSC_RIMC_CR_TDCID_MASK (7 << RIFSC_RIMC_CR_TDCID_SHIFT) 164 | #define RIFSC_RIMC_CR_TDCID_VALUE ((TDCID) << RIFSC_RIMC_CR_TDCID_SHIFT) 165 | 166 | /* Bootfail red LED on PH4 */ 167 | #define LED_GPIO_BASE 0x442b0000 168 | #define LED_GPIO_ODR_OFFSET 0x014 169 | #define LED_GPIO_MASK BIT(4) 170 | 171 | static inline void write32(unsigned long addr, uint32_t val) 172 | { 173 | volatile uint32_t *a = (uint32_t *)addr; 174 | 175 | *a = val; 176 | } 177 | 178 | static inline uint32_t read32(unsigned long addr) 179 | { 180 | volatile uint32_t *a = (uint32_t *)addr; 181 | 182 | return *a; 183 | } 184 | 185 | static inline void setbits32(unsigned long addr, uint32_t val) 186 | { 187 | volatile uint32_t *a = (uint32_t *)addr; 188 | 189 | *a = *a | val; 190 | } 191 | 192 | static inline void clrbits32(unsigned long addr, uint32_t val) 193 | { 194 | volatile uint32_t *a = (uint32_t *)addr; 195 | 196 | *a = *a & ~val; 197 | } 198 | 199 | void _start(void) __attribute__ ((noreturn)); 200 | void _start(void) 201 | { 202 | #ifdef __GCC_HAVE_DWARF2_CFI_ASM 203 | asm(".cfi_undefined lr"); 204 | asm(".cfi_undefined sp"); 205 | #endif 206 | 207 | uint32_t loc_fsbl_ptr; 208 | 209 | /* skip wrapper if not CM33-TD */ 210 | uint32_t rifsc_rimc_cr = read32(RIFSC_RIMC_BASE + RIFSC_RIMC_CR_OFFSET); 211 | if ((rifsc_rimc_cr & RIFSC_RIMC_CR_TDCID_MASK) != RIFSC_RIMC_CR_TDCID_VALUE) 212 | goto wrapper_exit; 213 | 214 | /* halt on first reset, wait for second one */ 215 | uint32_t double_boot = read32(BSEC_BASE + BSEC_SCRATCHR1_OFFSET); 216 | write32(BSEC_BASE + BSEC_SCRATCHR1_OFFSET, BSEC_SCRATCHR1_VAL); 217 | if (double_boot != BSEC_SCRATCHR1_VAL) 218 | while (1) {}; 219 | 220 | /* open debug early, as DBGSWEN is required to access DBGMCU */ 221 | write32(BSEC_BASE + BSEC_DENR_OFFSET, BSEC_DENR_VAL); 222 | 223 | write32(BSEC_BASE + BSEC_DBGACR_OFFSET, BSEC_DBGXCR_ENABLE); 224 | write32(BSEC_BASE + BSEC_DBGMCR_OFFSET, BSEC_DBGXCR_ENABLE); 225 | write32(BSEC_BASE + BSEC_AP_UNLOCK_OFFSET, BSEC_AP_UNLOCK_ENABLE); 226 | 227 | setbits32(RCC_BASE + RCC_DBGCFGR_OFFSET, RCC_DBGCFGR_DBGMCUEN); 228 | 229 | /* 230 | * wait for clock enabled 231 | * don't unroll, add dummy asm to prevent optimizations 232 | */ 233 | #pragma GCC unroll 1 234 | for (unsigned int i = RCC_DELAY_N; i; i--) 235 | asm(""); 236 | 237 | write32(DBGMCU_BASE + DBGMCU_DBG_AUTH_DEV_OFFSET, 0); 238 | 239 | /* Prevent CA35 to sleep and signal the debugger that there is a wrapper */ 240 | write32(DBGMCU_BASE + DBGMCU_CR_OFFSET, DBGMCU_CR_VAL1); 241 | 242 | /* Initialize systick */ 243 | write32(CM33_SYST_BASE + CM33_SYST_RVR_OFFSET, CM33_SYST_RELOAD_VALUE); 244 | write32(CM33_SYST_BASE + CM33_SYST_CSR_OFFSET, CM33_SYST_CSR_ENABLE); 245 | write32(CM33_SYST_BASE + CM33_SYST_CVR_OFFSET, CM33_SYST_CSR_ENABLE); 246 | 247 | /* wait for debugger or timeout, blinking the LED */ 248 | uint32_t led = read32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET); 249 | for (unsigned int timeout = CM33_SYST_RELOADS; timeout; ) { 250 | if (read32(DBGMCU_BASE + DBGMCU_CR_OFFSET) != DBGMCU_CR_VAL1) 251 | break; 252 | 253 | if (read32(CM33_SYST_BASE + CM33_SYST_CSR_OFFSET) & CM33_SYST_CSR_CNTFLG_MASK) { 254 | led ^= LED_GPIO_MASK; 255 | write32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET, led); 256 | timeout--; 257 | } 258 | } 259 | 260 | /* LED off */ 261 | write32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET, led | LED_GPIO_MASK); 262 | 263 | /* does debugger ask to halt? */ 264 | if (read32(CM33_DHCSR_BASE) & CM33_DHCSR_C_DEBUGEN) { 265 | /* set HW breakpoint at FSBL-M */ 266 | asm("ldr %0, fsbl_ptr" : "=r" (loc_fsbl_ptr)); 267 | write32(CM33_FP_BASE + CM33_FP_CTRL_OFFSET, CM33_FP_CTRL_ENABLE); 268 | write32(CM33_FP_BASE + CM33_FP_COMP_OFFSET(0), loc_fsbl_ptr | CM33_FP_COMP_ENABLE); 269 | } 270 | 271 | /* final value in DBGMCU_CR */ 272 | write32(DBGMCU_BASE + DBGMCU_CR_OFFSET, DBGMCU_CR_VAL2); 273 | 274 | wrapper_exit: 275 | 276 | asm("ldr %0, fsbl_ptr" : "=r" (loc_fsbl_ptr)); 277 | 278 | /* Set reset vector back to FSBL-M, as wrapper could be overwritten */ 279 | write32(CM33_RESET_VECTOR + CM33_RESET_VECTOR_PC_OFFSET, loc_fsbl_ptr); 280 | 281 | /* at last, jump to FSBL-M */ 282 | asm("bx %0" : : "r" (loc_fsbl_ptr)); 283 | 284 | /* validate attribute noreturn */ 285 | while (1) {}; 286 | } 287 | 288 | // vi:nospell 289 | -------------------------------------------------------------------------------- /wrapper_stm32mp21x_cm33.inc: -------------------------------------------------------------------------------- 1 | /* Generated automatically by Makefile */ 2 | 0x2d,0x4b,0xd3,0xf8,0x00,0x3c,0x03,0xf0,0x70,0x03,0x20,0x2b,0x3e,0xd1,0x4f,0xf0, 3 | 0x88,0x43,0x01,0x21,0xd3,0xf8,0x04,0x2e,0xc3,0xf8,0x04,0x1e,0x8a,0x42,0x00,0xd0, 4 | 0xfe,0xe7,0x26,0x4a,0xc3,0xf8,0x20,0x2e,0x25,0x4a,0xc3,0xf8,0xac,0x2e,0xc3,0xf8, 5 | 0x8c,0x2e,0xb4,0x22,0xc3,0xf8,0x90,0x2e,0x22,0x4a,0xd2,0xf8,0x20,0x35,0x43,0xf4, 6 | 0x80,0x63,0xc2,0xf8,0x20,0x35,0x10,0x23,0x01,0x3b,0xfd,0xd1,0x1e,0x48,0x4f,0xf0, 7 | 0xe0,0x22,0xc0,0xf8,0x04,0x31,0x04,0x23,0x43,0x60,0x1c,0x4b,0x40,0x21,0x53,0x61, 8 | 0x05,0x23,0x1b,0x4c,0x13,0x61,0x93,0x61,0x63,0x69,0x11,0xb1,0x45,0x68,0x04,0x2d, 9 | 0x11,0xd0,0x17,0x4a,0x43,0xf0,0x10,0x03,0x53,0x61,0x4f,0xf0,0xe0,0x23,0xd3,0xf8, 10 | 0xf0,0x3d,0xdb,0x07,0x10,0xd4,0x07,0x22,0x0f,0x4b,0x5a,0x60,0x11,0x4a,0x13,0x4b, 11 | 0x53,0x60,0x18,0x47,0xfe,0xe7,0x15,0x69,0xed,0x03,0x42,0xbf,0x83,0xf0,0x10,0x03, 12 | 0x63,0x61,0x01,0xf1,0xff,0x31,0xe0,0xe7,0x03,0x21,0x0c,0x4b,0x0a,0x4a,0x43,0xf0, 13 | 0x01,0x03,0x11,0x60,0x93,0x60,0xe6,0xe7,0x00,0x00,0x08,0x42,0xff,0xcf,0xb3,0xde, 14 | 0x00,0xb4,0xb4,0xb4,0x00,0x00,0x20,0x44,0x00,0x00,0x0a,0x44,0x18,0x0d,0x8f,0x00, 15 | 0x00,0x00,0x2b,0x44,0x00,0x00,0x04,0x0e,0x00,0x20,0x00,0xe0, 16 | -------------------------------------------------------------------------------- /wrapper_stm32mp25x_ca35.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ 2 | /* 3 | * Copyright (c) 2019-2024, STMicroelectronics - All Rights Reserved 4 | * Author: Antonio Borneo 5 | */ 6 | 7 | /* 8 | * ARM: https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/arm/aout.h 9 | * arm-none-eabi-gcc -Os -fcall-used-r4 -fcall-used-r5 -ffixed-r7 -ffixed-r11 -ffixed-r14 -fconserve-stack -c x.c -Wstack-usage=0 10 | * arm-none-eabi-gcc -Os -fcall-used-r4 -fcall-used-r5 -ffixed-r7 -ffixed-r11 -ffixed-r14 -fconserve-stack -fomit-frame-pointer -mcpu=cortex-m33 -mthumb -c x.c -Wstack-usage=0 11 | * arm-none-eabi-objdump -d x.o 12 | * 13 | * 0, 1, 2, 3, 4, 5, 6, X, 14 | * 8, 9, 10, X, 12, X, X, X, 15 | * 16 | * #define ARM_HARD_FRAME_POINTER_REGNUM 11 17 | * #define THUMB_HARD_FRAME_POINTER_REGNUM 7 18 | * 19 | * "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 20 | * "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc", 21 | * 22 | * https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/arm/arm.h 23 | * Register allocation in ARM Procedure Call Standard 24 | * (S - saved over call, F - Frame-related). 25 | * 26 | * r0 * argument word/integer result 27 | * r1-r3 argument word 28 | * 29 | * r4-r8 S register variable 30 | * r9 S (rfp) register variable (real frame pointer) 31 | * 32 | * r10 F S (sl) stack limit (used by -mapcs-stack-check) 33 | * r11 F S (fp) argument pointer 34 | * r12 (ip) temp workspace 35 | * r13 F S (sp) lower end of current stack frame 36 | * r14 (lr) link address/workspace 37 | * r15 F (pc) program counter 38 | * 39 | * 40 | * AARCH64: https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/aarch64/aarch64.h 41 | * aarch64-linux-gnu-gcc -Os -Wall -Wstack-usage=0 -mcpu=cortex-a35 -fcall-used-x19 -fcall-used-x20 -fcall-used-x21 -fcall-used-x22 -fcall-used-x23 -fcall-used-x24 -fcall-used-x25 \ 42 | * -fcall-used-x26 -fcall-used-x27 -fcall-used-x28 -fconserve-stack -fomit-frame-pointer -ffixed-x30 -c x.c 43 | * aarch64-linux-gnu-objdump -d firmware-example.o 44 | * 45 | * "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 46 | * "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 47 | * "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 48 | * "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp", 49 | * 50 | * 31 64-bit general purpose registers R0-R30: 51 | * R30 LR (link register) 52 | * R29 FP (frame pointer) 53 | * R19-R28 Callee-saved registers 54 | * R18 The platform register; use as temporary register. 55 | * R17 IP1 The second intra-procedure-call temporary register 56 | * (can be used by call veneers and PLT code); otherwise use 57 | * as a temporary register 58 | * R16 IP0 The first intra-procedure-call temporary register (can 59 | * be used by call veneers and PLT code); otherwise use as a 60 | * temporary register 61 | * R9-R15 Temporary registers 62 | * R8 Structure value parameter / temporary register 63 | * R0-R7 Parameter/result registers 64 | * 65 | * SP stack pointer, encoded as X/R31 where permitted. 66 | * ZR zero register, encoded as X/R31 elsewhere 67 | * 68 | * 32 x 128-bit floating-point/vector registers 69 | * V16-V31 Caller-saved (temporary) registers 70 | * V8-V15 Callee-saved registers 71 | * V0-V7 Parameter/result registers 72 | * 73 | * The vector register V0 holds scalar B0, H0, S0 and D0 in its least 74 | * significant bits. Unlike AArch32 S1 is not packed into D0, etc. 75 | * 76 | * P0-P7 Predicate low registers: valid in all predicate contexts 77 | * P8-P15 Predicate high registers: used as scratch space 78 | * 79 | * FFR First Fault Register, a fixed-use SVE predicate register 80 | * FFRT FFR token: a fake register used for modelling dependencies 81 | * 82 | * VG Pseudo "vector granules" register 83 | * 84 | * VG is the number of 64-bit elements in an SVE vector. We define 85 | * it as a hard register so that we can easily map it to the DWARF VG 86 | * register. GCC internally uses the poly_int variable aarch64_sve_vg 87 | * instead. 88 | */ 89 | 90 | #include 91 | 92 | #define BIT(x) (1UL << (x)) 93 | 94 | #define MPIDR_CPUID_MASK 0x0000ffff 95 | #define EDSCR_HDE_MASK BIT(14) 96 | #define DBGBCR0_EL1_VAL (BIT(13) | BIT(8) | BIT(7) | BIT(6) | BIT(5) | BIT(2) | BIT(1) | BIT(0)) 97 | //#define DBGBCR0_EL1_VAL 0x000021e7 98 | 99 | #define CNT_RELOADS_PER_S 32 100 | #define DELAY_S 2 101 | #define CNT_RELOADS (DELAY_S * CNT_RELOADS_PER_S) 102 | 103 | #define BSEC_BASE 0x44000000 104 | #define BSEC_DENR_OFFSET 0xe20 105 | #define BSEC_DENR_VAL 0xdeb60fff 106 | 107 | #define RCC_BASE 0x44200000 108 | #define RCC_DBGCFGR_OFFSET 0x520 109 | #define RCC_DBGCFGR_DBGEN BIT(8) 110 | 111 | #define DBGMCU_BASE 0x4a010000 112 | #define DBGMCU_CR_OFFSET 0x004 113 | #define DBGMCU_CR_VAL1 0x00000014 114 | #define DBGMCU_CR_VAL2 0x00000017 115 | 116 | #define TDCID 1 117 | 118 | #define RIFSC_RIMC_BASE 0x42080000 119 | #define RIFSC_RIMC_CR_OFFSET 0xc00 120 | #define RIFSC_RIMC_CR_TDCID_SHIFT 4 121 | #define RIFSC_RIMC_CR_TDCID_MASK (7 << RIFSC_RIMC_CR_TDCID_SHIFT) 122 | #define RIFSC_RIMC_CR_TDCID_VALUE ((TDCID) << RIFSC_RIMC_CR_TDCID_SHIFT) 123 | 124 | /* Bootfail red LED on PH4 */ 125 | #define LED_GPIO_BASE 0x442b0000 126 | #define LED_GPIO_ODR_OFFSET 0x014 127 | #define LED_GPIO_MASK BIT(4) 128 | 129 | #define STGENC_BASE 0x48080000 130 | #define STGENC_CNTFID0_OFFSET 0x020 131 | 132 | static inline void write32(unsigned long addr, uint32_t val) 133 | { 134 | volatile uint32_t *a = (uint32_t *)addr; 135 | 136 | *a = val; 137 | } 138 | 139 | static inline uint32_t read32(unsigned long addr) 140 | { 141 | volatile uint32_t *a = (uint32_t *)addr; 142 | 143 | return *a; 144 | } 145 | 146 | static inline void setbits32(unsigned long addr, uint32_t val) 147 | { 148 | volatile uint32_t *a = (uint32_t *)addr; 149 | 150 | *a = *a | val; 151 | } 152 | 153 | static inline void clrbits32(unsigned long addr, uint32_t val) 154 | { 155 | volatile uint32_t *a = (uint32_t *)addr; 156 | 157 | *a = *a & ~val; 158 | } 159 | 160 | void _start(void) __attribute__ ((noreturn)); 161 | void _start(void) 162 | { 163 | #ifdef __GCC_HAVE_DWARF2_CFI_ASM 164 | asm(".cfi_undefined lr"); 165 | asm(".cfi_undefined sp"); 166 | #endif 167 | 168 | uint32_t loc_fsbl_ptr; 169 | uint32_t edscr; 170 | 171 | /* skip wrapper if not CM33-TD */ 172 | uint32_t rifsc_rimc_cr = read32(RIFSC_RIMC_BASE + RIFSC_RIMC_CR_OFFSET); 173 | if ((rifsc_rimc_cr & RIFSC_RIMC_CR_TDCID_MASK) != RIFSC_RIMC_CR_TDCID_VALUE) 174 | goto wrapper_exit; 175 | 176 | /* put secondary cores in pen-hold */ 177 | uint64_t mpidr_el1; 178 | asm("mrs %0, mpidr_el1" : "=r" (mpidr_el1)); 179 | if (mpidr_el1 & MPIDR_CPUID_MASK) { 180 | asm("wfe"); 181 | goto pen_hold_exit; 182 | } 183 | 184 | /* open debug early, as DBGSWEN is required to access DBGMCU */ 185 | write32(BSEC_BASE + BSEC_DENR_OFFSET, BSEC_DENR_VAL); 186 | 187 | setbits32(RCC_BASE + RCC_DBGCFGR_OFFSET, RCC_DBGCFGR_DBGEN); 188 | (void)read32(RCC_BASE + RCC_DBGCFGR_OFFSET); 189 | 190 | /* Prevent CA35 to sleep and signal the debugger that there is a wrapper */ 191 | write32(DBGMCU_BASE + DBGMCU_CR_OFFSET, DBGMCU_CR_VAL1); 192 | 193 | /* 194 | * BootROM does not set cntfrq_el0. Use stgenc_cntfid0 value instead of 195 | * mrs x6, cntfrq_el0 196 | */ 197 | uint32_t delta = read32(STGENC_BASE + STGENC_CNTFID0_OFFSET) / CNT_RELOADS_PER_S; 198 | uint64_t cnt, next_cnt; 199 | asm("mrs %0, cntpct_el0" : "=r" (cnt)); 200 | next_cnt = cnt + delta; 201 | 202 | /* wait for debugger or timeout, blinking the LED */ 203 | uint32_t led = read32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET); 204 | for (unsigned int timeout = CNT_RELOADS; timeout; ) { 205 | if (read32(DBGMCU_BASE + DBGMCU_CR_OFFSET) != DBGMCU_CR_VAL1) 206 | break; 207 | 208 | asm volatile ("mrs %0, cntpct_el0" : "=r" (cnt)); 209 | if (cnt > next_cnt) { 210 | led ^= LED_GPIO_MASK; 211 | write32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET, led); 212 | next_cnt += delta; 213 | timeout--; 214 | } 215 | } 216 | 217 | /* LED off */ 218 | write32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET, led | LED_GPIO_MASK); 219 | 220 | /* final value in DBGMCU_CR */ 221 | write32(DBGMCU_BASE + DBGMCU_CR_OFFSET, DBGMCU_CR_VAL2); 222 | 223 | /* secondary cores out of pen-hold */ 224 | asm("sev"); 225 | 226 | pen_hold_exit: 227 | 228 | /* does debugger ask to halt? */ 229 | asm("mrs %0, mdscr_el1" : "=r" (edscr)); 230 | if (edscr & EDSCR_HDE_MASK) { 231 | /* set HW breakpoint at FSBL-A */ 232 | asm("ldr %w0, fsbl_ptr" : "=r" (loc_fsbl_ptr)); 233 | asm("msr dbgbvr0_el1, %0" : : "r" (loc_fsbl_ptr)); 234 | asm("msr dbgbcr0_el1, %0" : : "r" (DBGBCR0_EL1_VAL)); 235 | } 236 | 237 | wrapper_exit: 238 | 239 | asm("ldr %w0, fsbl_ptr" : "=r" (loc_fsbl_ptr)); 240 | 241 | /* at last, jump to FSBL-A */ 242 | asm("br %0" : : "r" (loc_fsbl_ptr)); 243 | 244 | /* validate attribute noreturn */ 245 | while (1) {}; 246 | } 247 | 248 | // vi:nospell 249 | -------------------------------------------------------------------------------- /wrapper_stm32mp25x_ca35.inc: -------------------------------------------------------------------------------- 1 | /* Generated automatically by Makefile */ 2 | 0x00,0x80,0x81,0xd2,0x00,0x41,0xa8,0xf2,0x00,0x00,0x40,0xb9,0x00,0x08,0x1c,0x12, 3 | 0x1f,0x40,0x00,0x71,0x61,0x01,0x00,0x54,0xa0,0x00,0x38,0xd5,0x1f,0x3c,0x00,0x72, 4 | 0x60,0x01,0x00,0x54,0x5f,0x20,0x03,0xd5,0x40,0x02,0x30,0xd5,0xa0,0x00,0x70,0x36, 5 | 0x80,0x06,0x00,0x18,0x80,0x00,0x10,0xd5,0xe0,0x3c,0x84,0xd2,0xa0,0x00,0x10,0xd5, 6 | 0x00,0x06,0x00,0x18,0x00,0x00,0x1f,0xd6,0x00,0x00,0x00,0x14,0x00,0xc4,0x81,0xd2, 7 | 0x00,0x80,0xa8,0xf2,0xe1,0xff,0x81,0x52,0xc1,0xd6,0xbb,0x72,0x01,0x00,0x00,0xb9, 8 | 0x00,0xa4,0x80,0xd2,0x00,0x84,0xa8,0xf2,0x83,0x00,0x80,0xd2,0x23,0x40,0xa9,0xf2, 9 | 0x01,0x00,0x40,0xb9,0x85,0x02,0x80,0xd2,0x65,0x85,0xa8,0xf2,0x21,0x00,0x18,0x32, 10 | 0x01,0x00,0x00,0xb9,0x04,0x08,0x80,0x52,0x00,0x00,0x40,0xb9,0x80,0x02,0x80,0x52, 11 | 0x60,0x00,0x00,0xb9,0x00,0x04,0x80,0xd2,0x00,0x01,0xa9,0xf2,0x02,0x00,0x40,0xb9, 12 | 0xa1,0x00,0x40,0xb9,0x20,0xe0,0x3b,0xd5,0x42,0x7c,0x05,0x53,0x40,0x00,0x00,0x8b, 13 | 0x84,0x00,0x00,0x34,0x66,0x00,0x40,0xb9,0xdf,0x50,0x00,0x71,0x20,0x01,0x00,0x54, 14 | 0x80,0x02,0x80,0xd2,0x60,0x85,0xa8,0xf2,0x21,0x00,0x1c,0x32,0x01,0x00,0x00,0xb9, 15 | 0xe0,0x02,0x80,0x52,0x60,0x00,0x00,0xb9,0x9f,0x20,0x03,0xd5,0xd3,0xff,0xff,0x17, 16 | 0x26,0xe0,0x3b,0xd5,0x1f,0x00,0x06,0xeb,0x42,0xfe,0xff,0x54,0x21,0x00,0x1c,0x52, 17 | 0x00,0x00,0x02,0x8b,0x84,0x04,0x00,0x51,0xa1,0x00,0x00,0xb9,0xed,0xff,0xff,0x17, 18 | -------------------------------------------------------------------------------- /wrapper_stm32mp25x_cm33.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ 2 | /* 3 | * Copyright (c) 2019-2024, STMicroelectronics - All Rights Reserved 4 | * Author: Antonio Borneo 5 | */ 6 | 7 | /* 8 | * ARM: https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/arm/aout.h 9 | * arm-none-eabi-gcc -Os -fcall-used-r4 -fcall-used-r5 -ffixed-r7 -ffixed-r11 -ffixed-r14 -fconserve-stack -c x.c -Wstack-usage=0 10 | * arm-none-eabi-gcc -Os -fcall-used-r4 -fcall-used-r5 -ffixed-r7 -ffixed-r11 -ffixed-r14 -fconserve-stack -fomit-frame-pointer -mcpu=cortex-m33 -mthumb -c x.c -Wstack-usage=0 11 | * arm-none-eabi-objdump -d x.o 12 | * 13 | * 0, 1, 2, 3, 4, 5, 6, X, 14 | * 8, 9, 10, X, 12, X, X, X, 15 | * 16 | * #define ARM_HARD_FRAME_POINTER_REGNUM 11 17 | * #define THUMB_HARD_FRAME_POINTER_REGNUM 7 18 | * 19 | * "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 20 | * "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc", 21 | * 22 | * https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/arm/arm.h 23 | * Register allocation in ARM Procedure Call Standard 24 | * (S - saved over call, F - Frame-related). 25 | * 26 | * r0 * argument word/integer result 27 | * r1-r3 argument word 28 | * 29 | * r4-r8 S register variable 30 | * r9 S (rfp) register variable (real frame pointer) 31 | * 32 | * r10 F S (sl) stack limit (used by -mapcs-stack-check) 33 | * r11 F S (fp) argument pointer 34 | * r12 (ip) temp workspace 35 | * r13 F S (sp) lower end of current stack frame 36 | * r14 (lr) link address/workspace 37 | * r15 F (pc) program counter 38 | * 39 | * 40 | * AARCH64: https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/aarch64/aarch64.h 41 | * aarch64-linux-gnu-gcc -Os -Wall -Wstack-usage=0 -mcpu=cortex-a35 -fcall-used-x19 -fcall-used-x20 -fcall-used-x21 -fcall-used-x22 -fcall-used-x23 -fcall-used-x24 -fcall-used-x25 \ 42 | * -fcall-used-x26 -fcall-used-x27 -fcall-used-x28 -fconserve-stack -fomit-frame-pointer -ffixed-x30 -c x.c 43 | * aarch64-linux-gnu-objdump -d firmware-example.o 44 | * 45 | * "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 46 | * "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 47 | * "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 48 | * "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp", 49 | * 50 | * 31 64-bit general purpose registers R0-R30: 51 | * R30 LR (link register) 52 | * R29 FP (frame pointer) 53 | * R19-R28 Callee-saved registers 54 | * R18 The platform register; use as temporary register. 55 | * R17 IP1 The second intra-procedure-call temporary register 56 | * (can be used by call veneers and PLT code); otherwise use 57 | * as a temporary register 58 | * R16 IP0 The first intra-procedure-call temporary register (can 59 | * be used by call veneers and PLT code); otherwise use as a 60 | * temporary register 61 | * R9-R15 Temporary registers 62 | * R8 Structure value parameter / temporary register 63 | * R0-R7 Parameter/result registers 64 | * 65 | * SP stack pointer, encoded as X/R31 where permitted. 66 | * ZR zero register, encoded as X/R31 elsewhere 67 | * 68 | * 32 x 128-bit floating-point/vector registers 69 | * V16-V31 Caller-saved (temporary) registers 70 | * V8-V15 Callee-saved registers 71 | * V0-V7 Parameter/result registers 72 | * 73 | * The vector register V0 holds scalar B0, H0, S0 and D0 in its least 74 | * significant bits. Unlike AArch32 S1 is not packed into D0, etc. 75 | * 76 | * P0-P7 Predicate low registers: valid in all predicate contexts 77 | * P8-P15 Predicate high registers: used as scratch space 78 | * 79 | * FFR First Fault Register, a fixed-use SVE predicate register 80 | * FFRT FFR token: a fake register used for modelling dependencies 81 | * 82 | * VG Pseudo "vector granules" register 83 | * 84 | * VG is the number of 64-bit elements in an SVE vector. We define 85 | * it as a hard register so that we can easily map it to the DWARF VG 86 | * register. GCC internally uses the poly_int variable aarch64_sve_vg 87 | * instead. 88 | */ 89 | 90 | #include 91 | 92 | #define BIT(x) (1UL << (x)) 93 | 94 | #define CPU_FREQ_HZ 300000000 95 | #define CM33_SYST_FREQ_HZ CPU_FREQ_HZ 96 | #define CM33_SYST_RELOADS_PER_S 32 97 | #define CM33_SYST_RELOAD_VALUE ((CM33_SYST_FREQ_HZ) / (CM33_SYST_RELOADS_PER_S)) 98 | #define DELAY_S 2 99 | #define CM33_SYST_RELOADS (DELAY_S * CM33_SYST_RELOADS_PER_S) 100 | 101 | /* must fit in 24 bits */ 102 | #if CM33_SYST_RELOAD_VALUE > 0x00ffffff 103 | #error SYST out of range, increase CM33_SYST_RELOADS_PER_S 104 | #endif 105 | 106 | #define CM33_RESET_VECTOR 0x0e080000 107 | #define CM33_RESET_VECTOR_PC_OFFSET 0x004 108 | 109 | #define CM33_SYST_BASE 0xe000e010 110 | #define CM33_SYST_CSR_OFFSET 0x000 111 | #define CM33_SYST_RVR_OFFSET 0x004 112 | #define CM33_SYST_CVR_OFFSET 0x008 113 | #define CM33_SYST_CSR_ENABLE (BIT(2) | BIT(0)) 114 | #define CM33_SYST_CSR_CNTFLG_MASK BIT(16) 115 | 116 | #define CM33_FP_BASE 0xe0002000 117 | #define CM33_FP_CTRL_OFFSET 0x000 118 | #define CM33_FP_COMP_OFFSET(n) (0x008 + 4 * (n)) 119 | #define CM33_FP_CTRL_ENABLE (BIT(1) | BIT(0)) 120 | #define CM33_FP_COMP_ENABLE BIT(0) 121 | 122 | #define CM33_DHCSR_BASE 0xe000edf0 123 | #define CM33_DHCSR_C_DEBUGEN BIT(0) 124 | 125 | #define BSEC_BASE 0x44000000 126 | #define BSEC_SCRATCHR1_OFFSET 0xe04 127 | #define BSEC_SCRATCHR1_VAL 1 128 | #define BSEC_DENR_OFFSET 0xe20 129 | #define BSEC_DENR_VAL 0xdeb60fff 130 | 131 | #define RCC_BASE 0x44200000 132 | #define RCC_DBGCFGR_OFFSET 0x520 133 | #define RCC_DBGCFGR_DBGEN BIT(8) 134 | #define RCC_DELAY_N 16 /* (N >= 5) */ 135 | 136 | #define DBGMCU_BASE 0x4a010000 137 | #define DBGMCU_CR_OFFSET 0x004 138 | #define DBGMCU_CR_VAL1 0x00000014 139 | #define DBGMCU_CR_VAL2 0x00000017 140 | 141 | #define TDCID 2 142 | 143 | #define RIFSC_RIMC_BASE 0x42080000 144 | #define RIFSC_RIMC_CR_OFFSET 0xc00 145 | #define RIFSC_RIMC_CR_TDCID_SHIFT 4 146 | #define RIFSC_RIMC_CR_TDCID_MASK (7 << RIFSC_RIMC_CR_TDCID_SHIFT) 147 | #define RIFSC_RIMC_CR_TDCID_VALUE ((TDCID) << RIFSC_RIMC_CR_TDCID_SHIFT) 148 | 149 | /* Bootfail red LED on PH4 */ 150 | #define LED_GPIO_BASE 0x442b0000 151 | #define LED_GPIO_ODR_OFFSET 0x014 152 | #define LED_GPIO_MASK BIT(4) 153 | 154 | static inline void write32(unsigned long addr, uint32_t val) 155 | { 156 | volatile uint32_t *a = (uint32_t *)addr; 157 | 158 | *a = val; 159 | } 160 | 161 | static inline uint32_t read32(unsigned long addr) 162 | { 163 | volatile uint32_t *a = (uint32_t *)addr; 164 | 165 | return *a; 166 | } 167 | 168 | static inline void setbits32(unsigned long addr, uint32_t val) 169 | { 170 | volatile uint32_t *a = (uint32_t *)addr; 171 | 172 | *a = *a | val; 173 | } 174 | 175 | static inline void clrbits32(unsigned long addr, uint32_t val) 176 | { 177 | volatile uint32_t *a = (uint32_t *)addr; 178 | 179 | *a = *a & ~val; 180 | } 181 | 182 | void _start(void) __attribute__ ((noreturn)); 183 | void _start(void) 184 | { 185 | #ifdef __GCC_HAVE_DWARF2_CFI_ASM 186 | asm(".cfi_undefined lr"); 187 | asm(".cfi_undefined sp"); 188 | #endif 189 | 190 | uint32_t loc_fsbl_ptr; 191 | 192 | /* skip wrapper if not CM33-TD */ 193 | uint32_t rifsc_rimc_cr = read32(RIFSC_RIMC_BASE + RIFSC_RIMC_CR_OFFSET); 194 | if ((rifsc_rimc_cr & RIFSC_RIMC_CR_TDCID_MASK) != RIFSC_RIMC_CR_TDCID_VALUE) 195 | goto wrapper_exit; 196 | 197 | /* halt on first reset, wait for second one */ 198 | uint32_t double_boot = read32(BSEC_BASE + BSEC_SCRATCHR1_OFFSET); 199 | write32(BSEC_BASE + BSEC_SCRATCHR1_OFFSET, BSEC_SCRATCHR1_VAL); 200 | if (double_boot != BSEC_SCRATCHR1_VAL) 201 | while (1) {}; 202 | 203 | /* open debug early, as DBGSWEN is required to access DBGMCU */ 204 | write32(BSEC_BASE + BSEC_DENR_OFFSET, BSEC_DENR_VAL); 205 | 206 | setbits32(RCC_BASE + RCC_DBGCFGR_OFFSET, RCC_DBGCFGR_DBGEN); 207 | /* 208 | * wait for clock enabled 209 | * don't unroll, add dummy asm to prevent optimizations 210 | */ 211 | #pragma GCC unroll 1 212 | for (unsigned int i = RCC_DELAY_N; i; i--) 213 | asm(""); 214 | 215 | /* Prevent CA35 to sleep and signal the debugger that there is a wrapper */ 216 | write32(DBGMCU_BASE + DBGMCU_CR_OFFSET, DBGMCU_CR_VAL1); 217 | 218 | /* Initialize systick */ 219 | write32(CM33_SYST_BASE + CM33_SYST_RVR_OFFSET, CM33_SYST_RELOAD_VALUE); 220 | write32(CM33_SYST_BASE + CM33_SYST_CSR_OFFSET, CM33_SYST_CSR_ENABLE); 221 | write32(CM33_SYST_BASE + CM33_SYST_CVR_OFFSET, CM33_SYST_CSR_ENABLE); 222 | 223 | /* wait for debugger or timeout, blinking the LED */ 224 | uint32_t led = read32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET); 225 | for (unsigned int timeout = CM33_SYST_RELOADS; timeout; ) { 226 | if (read32(DBGMCU_BASE + DBGMCU_CR_OFFSET) != DBGMCU_CR_VAL1) 227 | break; 228 | 229 | if (read32(CM33_SYST_BASE + CM33_SYST_CSR_OFFSET) & CM33_SYST_CSR_CNTFLG_MASK) { 230 | led ^= LED_GPIO_MASK; 231 | write32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET, led); 232 | timeout--; 233 | } 234 | } 235 | 236 | /* LED off */ 237 | write32(LED_GPIO_BASE + LED_GPIO_ODR_OFFSET, led | LED_GPIO_MASK); 238 | 239 | /* does debugger ask to halt? */ 240 | if (read32(CM33_DHCSR_BASE) & CM33_DHCSR_C_DEBUGEN) { 241 | /* set HW breakpoint at FSBL-M */ 242 | asm("ldr %0, fsbl_ptr" : "=r" (loc_fsbl_ptr)); 243 | write32(CM33_FP_BASE + CM33_FP_CTRL_OFFSET, CM33_FP_CTRL_ENABLE); 244 | write32(CM33_FP_BASE + CM33_FP_COMP_OFFSET(0), loc_fsbl_ptr | CM33_FP_COMP_ENABLE); 245 | } 246 | 247 | /* final value in DBGMCU_CR */ 248 | write32(DBGMCU_BASE + DBGMCU_CR_OFFSET, DBGMCU_CR_VAL2); 249 | 250 | wrapper_exit: 251 | 252 | asm("ldr %0, fsbl_ptr" : "=r" (loc_fsbl_ptr)); 253 | 254 | /* Set reset vector back to FSBL-M, as wrapper could be overwritten */ 255 | write32(CM33_RESET_VECTOR + CM33_RESET_VECTOR_PC_OFFSET, loc_fsbl_ptr); 256 | 257 | /* at last, jump to FSBL-M */ 258 | asm("bx %0" : : "r" (loc_fsbl_ptr)); 259 | 260 | /* validate attribute noreturn */ 261 | while (1) {}; 262 | } 263 | 264 | // vi:nospell 265 | -------------------------------------------------------------------------------- /wrapper_stm32mp25x_cm33.inc: -------------------------------------------------------------------------------- 1 | /* Generated automatically by Makefile */ 2 | 0x28,0x4b,0xd3,0xf8,0x00,0x3c,0x03,0xf0,0x70,0x03,0x20,0x2b,0x34,0xd1,0x4f,0xf0, 3 | 0x88,0x43,0x01,0x21,0xd3,0xf8,0x04,0x2e,0xc3,0xf8,0x04,0x1e,0x8a,0x42,0x00,0xd0, 4 | 0xfe,0xe7,0x21,0x4a,0xc3,0xf8,0x20,0x2e,0x20,0x4a,0xd2,0xf8,0x20,0x35,0x43,0xf4, 5 | 0x80,0x73,0xc2,0xf8,0x20,0x35,0x10,0x23,0x01,0x3b,0xfd,0xd1,0x14,0x23,0x4f,0xf0, 6 | 0xe0,0x22,0x1b,0x48,0x40,0x21,0x43,0x60,0x1a,0x4b,0x1b,0x4c,0x53,0x61,0x05,0x23, 7 | 0x13,0x61,0x93,0x61,0x63,0x69,0x11,0xb1,0x45,0x68,0x14,0x2d,0x11,0xd0,0x16,0x4a, 8 | 0x43,0xf0,0x10,0x03,0x53,0x61,0x4f,0xf0,0xe0,0x23,0xd3,0xf8,0xf0,0x3d,0xdb,0x07, 9 | 0x10,0xd4,0x17,0x22,0x0e,0x4b,0x5a,0x60,0x10,0x4a,0x12,0x4b,0x53,0x60,0x18,0x47, 10 | 0xfe,0xe7,0x15,0x69,0xed,0x03,0x42,0xbf,0x83,0xf0,0x10,0x03,0x63,0x61,0x01,0xf1, 11 | 0xff,0x31,0xe0,0xe7,0x03,0x21,0x0b,0x4b,0x09,0x4a,0x43,0xf0,0x01,0x03,0x11,0x60, 12 | 0x93,0x60,0xe6,0xe7,0x00,0x00,0x08,0x42,0xff,0x0f,0xb6,0xde,0x00,0x00,0x20,0x44, 13 | 0x00,0x00,0x01,0x4a,0x18,0x0d,0x8f,0x00,0x00,0x00,0x2b,0x44,0x00,0x00,0x08,0x0e, 14 | 0x00,0x20,0x00,0xe0, 15 | --------------------------------------------------------------------------------