├── .cmake-format.py ├── .gitattributes ├── .github └── workflows │ └── codeql.yml ├── .gitignore ├── .gitlint ├── CHANGELOG.md ├── CMakeLists.txt ├── CMakePresets.json ├── CONTRIBUTING.md ├── COPYING ├── DESCRIPTION ├── README.md ├── SECURITY.md ├── VERSION ├── conanfile.py ├── get-version.py ├── gitlint └── rules.py ├── include ├── Doxyfile.in ├── helpers.h ├── metee.h └── meteepp.h ├── linux.cmake ├── meson.build ├── meson_options.txt ├── samples ├── CMakeLists.txt ├── meiuuid.c ├── meiuuid.h ├── metee_basic.c ├── metee_connect.c ├── metee_gsc.c ├── metee_mkhi.c └── metee_trc.c ├── src ├── Windows │ ├── LICENSE.WDK.Ms-LPL │ ├── metee.rc.in │ ├── metee_win.c │ ├── metee_win.h │ ├── metee_winhelpers.c │ └── public.h ├── linux │ ├── LICENSE.libmei │ ├── include │ │ └── linux │ │ │ └── mei.h │ ├── libmei.h │ ├── mei.c │ └── metee_linux.c └── uefi │ ├── heci_core.c │ ├── heci_core.h │ ├── heci_efi.c │ ├── heci_efi.h │ ├── metee_efi.c │ ├── metee_efi.h │ ├── pci_utils.c │ └── pci_utils.h ├── tests ├── AMTHI.h ├── CMakeLists.txt ├── MKHI.h ├── Main.cpp ├── gtest.cmake.in ├── metee_test.cpp ├── metee_test.h └── meteepp_test.cpp ├── version.cmake └── win32.cmake /.cmake-format.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # ---------------------------------- 3 | # Options affecting listfile parsing 4 | # ---------------------------------- 5 | with section("parse"): 6 | 7 | # Specify structure for custom cmake functions 8 | additional_commands = { 'format_and_lint': { 'kwargs': { 'CC': '*', 9 | 'CCDEPENDS': '*', 10 | 'CMAKE': '*', 11 | 'EXCLUDE': '*', 12 | 'JS': '*', 13 | 'PY': '*'}}, 14 | 'pkg_find': {'kwargs': {'PKG': '*'}}} 15 | 16 | # Specify variable tags. 17 | vartags = [] 18 | 19 | # Specify property tags. 20 | proptags = [] 21 | 22 | # ----------------------------- 23 | # Options affecting formatting. 24 | # ----------------------------- 25 | with section("format"): 26 | 27 | # How wide to allow formatted cmake files 28 | line_width = 80 29 | 30 | # How many spaces to tab for indent 31 | tab_size = 2 32 | 33 | # If an argument group contains more than this many sub-groups (parg or kwarg 34 | # groups) then force it to a vertical layout. 35 | max_subgroups_hwrap = 2 36 | 37 | # If a positional argument group contains more than this many arguments, then 38 | # force it to a vertical layout. 39 | max_pargs_hwrap = 6 40 | 41 | # If a cmdline positional group consumes more than this many lines without 42 | # nesting, then invalidate the layout (and nest) 43 | max_rows_cmdline = 2 44 | 45 | # If true, separate flow control names from their parentheses with a space 46 | separate_ctrl_name_with_space = False 47 | 48 | # If true, separate function names from parentheses with a space 49 | separate_fn_name_with_space = False 50 | 51 | # If a statement is wrapped to more than one line, than dangle the closing 52 | # parenthesis on its own line. 53 | dangle_parens = True 54 | 55 | # If the trailing parenthesis must be 'dangled' on its on line, then align it 56 | # to this reference: `prefix`: the start of the statement, `prefix-indent`: 57 | # the start of the statement, plus one indentation level, `child`: align to 58 | # the column of the arguments 59 | dangle_align = 'prefix' 60 | 61 | # If the statement spelling length (including space and parenthesis) is 62 | # smaller than this amount, then force reject nested layouts. 63 | min_prefix_chars = 4 64 | 65 | # If the statement spelling length (including space and parenthesis) is larger 66 | # than the tab width by more than this amount, then force reject un-nested 67 | # layouts. 68 | max_prefix_chars = 10 69 | 70 | # If a candidate layout is wrapped horizontally but it exceeds this many 71 | # lines, then reject the layout. 72 | max_lines_hwrap = 2 73 | 74 | # What style line endings to use in the output. 75 | line_ending = 'unix' 76 | 77 | # Format command names consistently as 'lower' or 'upper' case 78 | command_case = 'canonical' 79 | 80 | # Format keywords consistently as 'lower' or 'upper' case 81 | keyword_case = 'unchanged' 82 | 83 | # A list of command names which should always be wrapped 84 | always_wrap = [] 85 | 86 | # If true, the argument lists which are known to be sortable will be sorted 87 | # lexicographicall 88 | enable_sort = True 89 | 90 | # If true, the parsers may infer whether or not an argument list is sortable 91 | # (without annotation). 92 | autosort = False 93 | 94 | # By default, if cmake-format cannot successfully fit everything into the 95 | # desired linewidth it will apply the last, most aggressive attempt that it 96 | # made. If this flag is True, however, cmake-format will print error, exit 97 | # with non-zero status code, and write-out nothing 98 | require_valid_layout = False 99 | 100 | # A dictionary mapping layout nodes to a list of wrap decisions. See the 101 | # documentation for more information. 102 | layout_passes = {} 103 | 104 | # ------------------------------------------------ 105 | # Options affecting comment reflow and formatting. 106 | # ------------------------------------------------ 107 | with section("markup"): 108 | 109 | # What character to use for bulleted lists 110 | bullet_char = '*' 111 | 112 | # What character to use as punctuation after numerals in an enumerated list 113 | enum_char = '.' 114 | 115 | # If comment markup is enabled, don't reflow the first comment block in each 116 | # listfile. Use this to preserve formatting of your copyright/license 117 | # statements. 118 | first_comment_is_literal = False 119 | 120 | # If comment markup is enabled, don't reflow any comment block which matches 121 | # this (regex) pattern. Default is `None` (disabled). 122 | literal_comment_pattern = None 123 | 124 | # Regular expression to match preformat fences in comments default= 125 | # ``r'^\s*([`~]{3}[`~]*)(.*)$'`` 126 | fence_pattern = '^\\s*([`~]{3}[`~]*)(.*)$' 127 | 128 | # Regular expression to match rulers in comments default= 129 | # ``r'^\s*[^\w\s]{3}.*[^\w\s]{3}$'`` 130 | ruler_pattern = '^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$' 131 | 132 | # If a comment line matches starts with this pattern then it is explicitly a 133 | # trailing comment for the preceding argument. Default is '#<' 134 | explicit_trailing_pattern = '#<' 135 | 136 | # If a comment line starts with at least this many consecutive hash 137 | # characters, then don't lstrip() them off. This allows for lazy hash rulers 138 | # where the first hash char is not separated by space 139 | hashruler_min_length = 10 140 | 141 | # If true, then insert a space between the first hash char and remaining hash 142 | # chars in a hash ruler, and normalize its length to fill the column 143 | canonicalize_hashrulers = True 144 | 145 | # enable comment markup parsing and reflow 146 | enable_markup = True 147 | 148 | # ---------------------------- 149 | # Options affecting the linter 150 | # ---------------------------- 151 | with section("lint"): 152 | 153 | # a list of lint codes to disable 154 | disabled_codes = ['E1122', 'C0113'] 155 | 156 | # regular expression pattern describing valid function names 157 | function_pattern = '[0-9a-z_]+' 158 | 159 | # regular expression pattern describing valid macro names 160 | macro_pattern = '[0-9A-Z_]+' 161 | 162 | # regular expression pattern describing valid names for variables with global 163 | # scope 164 | global_var_pattern = '[0-9a-zA-Z][0-9a-zA-Z_]+' 165 | 166 | # regular expression pattern describing valid names for variables with global 167 | # scope (but internal semantic) 168 | internal_var_pattern = '_[0-9A-Z][0-9A-Z_]+' 169 | 170 | # regular expression pattern describing valid names for variables with local 171 | # scope 172 | local_var_pattern = '[0-9a-z_]+' 173 | 174 | # regular expression pattern describing valid names for privatedirectory 175 | # variables 176 | private_var_pattern = '_[0-9a-z_]+' 177 | 178 | # regular expression pattern describing valid names for publicdirectory 179 | # variables 180 | public_var_pattern = '[0-9A-Z][0-9A-Z_]+' 181 | 182 | # regular expression pattern describing valid names for keywords used in 183 | # functions or macros 184 | keyword_pattern = '[0-9A-Z_]+' 185 | 186 | # In the heuristic for C0201, how many conditionals to match within a loop in 187 | # before considering the loop a parser. 188 | max_conditionals_custom_parser = 2 189 | 190 | # Require at least this many newlines between statements 191 | min_statement_spacing = 1 192 | 193 | # Require no more than this many newlines between statements 194 | max_statement_spacing = 3 195 | max_returns = 6 196 | max_branches = 12 197 | max_arguments = 5 198 | max_localvars = 15 199 | max_statements = 50 200 | 201 | # ------------------------------- 202 | # Options affecting file encoding 203 | # ------------------------------- 204 | with section("encode"): 205 | 206 | # If true, emit the unicode byte-order mark (BOM) at the start of the file 207 | emit_byteorder_mark = False 208 | 209 | # Specify the encoding of the input file. Defaults to utf-8 210 | input_encoding = 'utf-8' 211 | 212 | # Specify the encoding of the output file. Defaults to utf-8. Note that cmake 213 | # only claims to support utf-8 so be careful when using anything else 214 | output_encoding = 'utf-8' 215 | 216 | # ------------------------------------- 217 | # Miscellaneous configurations options. 218 | # ------------------------------------- 219 | with section("misc"): 220 | 221 | # A dictionary containing any per-command configuration overrides. Currently 222 | # only `command_case` is supported. 223 | per_command = {} 224 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | permissions: read-all 3 | 4 | on: 5 | push: 6 | branches: [ "master" ] 7 | pull_request: 8 | # The branches below must be a subset of the branches above 9 | branches: [ "master" ] 10 | 11 | jobs: 12 | analyze: 13 | name: Analyze 14 | runs-on: ubuntu-latest 15 | permissions: 16 | actions: read 17 | contents: read 18 | security-events: write 19 | 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | language: [ 'c' ] 24 | 25 | steps: 26 | - name: Checkout repository 27 | uses: actions/checkout@v4 28 | 29 | # Initializes the CodeQL tools for scanning. 30 | - name: Initialize CodeQL 31 | uses: github/codeql-action/init@v3 32 | with: 33 | languages: ${{ matrix.language }} 34 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 35 | queries: +security-extended,security-and-quality 36 | 37 | 38 | - name: Autobuild 39 | uses: github/codeql-action/autobuild@v3 40 | 41 | - name: Perform CodeQL Analysis 42 | uses: github/codeql-action/analyze@v3 43 | with: 44 | category: "/language:${{matrix.language}}" 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.tlog 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Nuget personal access tokens and Credentials 210 | nuget.config 211 | 212 | # Microsoft Azure Build Output 213 | csx/ 214 | *.build.csdef 215 | 216 | # Microsoft Azure Emulator 217 | ecf/ 218 | rcf/ 219 | 220 | # Windows Store app package directories and files 221 | AppPackages/ 222 | BundleArtifacts/ 223 | Package.StoreAssociation.xml 224 | _pkginfo.txt 225 | *.appx 226 | *.appxbundle 227 | *.appxupload 228 | 229 | # Visual Studio cache files 230 | # files ending in .cache can be ignored 231 | *.[Cc]ache 232 | # but keep track of directories ending in .cache 233 | !?*.[Cc]ache/ 234 | 235 | # Others 236 | ClientBin/ 237 | ~$* 238 | *~ 239 | *.dbmdl 240 | *.dbproj.schemaview 241 | *.jfm 242 | *.pfx 243 | *.publishsettings 244 | orleans.codegen.cs 245 | 246 | # Including strong name files can present a security risk 247 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 248 | #*.snk 249 | 250 | # Since there are multiple workflows, uncomment next line to ignore bower_components 251 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 252 | #bower_components/ 253 | 254 | # RIA/Silverlight projects 255 | Generated_Code/ 256 | 257 | # Backup & report files from converting an old project file 258 | # to a newer Visual Studio version. Backup files are not needed, 259 | # because we have git ;-) 260 | _UpgradeReport_Files/ 261 | Backup*/ 262 | UpgradeLog*.XML 263 | UpgradeLog*.htm 264 | ServiceFabricBackup/ 265 | *.rptproj.bak 266 | 267 | # SQL Server files 268 | *.mdf 269 | *.ldf 270 | *.ndf 271 | 272 | # Business Intelligence projects 273 | *.rdl.data 274 | *.bim.layout 275 | *.bim_*.settings 276 | *.rptproj.rsuser 277 | *- [Bb]ackup.rdl 278 | *- [Bb]ackup ([0-9]).rdl 279 | *- [Bb]ackup ([0-9][0-9]).rdl 280 | 281 | # Microsoft Fakes 282 | FakesAssemblies/ 283 | 284 | # GhostDoc plugin setting file 285 | *.GhostDoc.xml 286 | 287 | # Node.js Tools for Visual Studio 288 | .ntvs_analysis.dat 289 | node_modules/ 290 | 291 | # Visual Studio 6 build log 292 | *.plg 293 | 294 | # Visual Studio 6 workspace options file 295 | *.opt 296 | 297 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 298 | *.vbw 299 | 300 | # Visual Studio LightSwitch build output 301 | **/*.HTMLClient/GeneratedArtifacts 302 | **/*.DesktopClient/GeneratedArtifacts 303 | **/*.DesktopClient/ModelManifest.xml 304 | **/*.Server/GeneratedArtifacts 305 | **/*.Server/ModelManifest.xml 306 | _Pvt_Extensions 307 | 308 | # Paket dependency manager 309 | .paket/paket.exe 310 | paket-files/ 311 | 312 | # FAKE - F# Make 313 | .fake/ 314 | 315 | # CodeRush personal settings 316 | .cr/personal 317 | 318 | # Python Tools for Visual Studio (PTVS) 319 | __pycache__/ 320 | *.pyc 321 | 322 | # Cake - Uncomment if you are using it 323 | # tools/** 324 | # !tools/packages.config 325 | 326 | # Tabs Studio 327 | *.tss 328 | 329 | # Telerik's JustMock configuration file 330 | *.jmconfig 331 | 332 | # BizTalk build output 333 | *.btp.cs 334 | *.btm.cs 335 | *.odx.cs 336 | *.xsd.cs 337 | 338 | # OpenCover UI analysis results 339 | OpenCover/ 340 | 341 | # Azure Stream Analytics local run output 342 | ASALocalRun/ 343 | 344 | # MSBuild Binary and Structured Log 345 | *.binlog 346 | 347 | # NVidia Nsight GPU debugger configuration file 348 | *.nvuser 349 | 350 | # MFractors (Xamarin productivity tool) working folder 351 | .mfractor/ 352 | 353 | # Local History for Visual Studio 354 | .localhistory/ 355 | 356 | # BeatPulse healthcheck temp database 357 | healthchecksdb 358 | 359 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 360 | MigrationBackup/ 361 | 362 | # Ionide (cross platform F# VS Code tools) working folder 363 | .ionide/ 364 | 365 | # Fody - auto-generated XML schema 366 | FodyWeavers.xsd 367 | 368 | # VS Code files for those working on multiple tools 369 | .vscode/* 370 | !.vscode/settings.json 371 | !.vscode/tasks.json 372 | !.vscode/launch.json 373 | !.vscode/extensions.json 374 | *.code-workspace 375 | 376 | # Local History for Visual Studio Code 377 | .history/ 378 | 379 | # Windows Installer files from build outputs 380 | *.cab 381 | *.msi 382 | *.msix 383 | *.msm 384 | *.msp 385 | 386 | # JetBrains Rider 387 | .idea/ 388 | *.sln.iml 389 | 390 | 391 | # Local files that should not be uploaded 392 | 393 | cmake.config 394 | CMakeSettings.json 395 | /CMakeUserPresets.json 396 | -------------------------------------------------------------------------------- /.gitlint: -------------------------------------------------------------------------------- 1 | # Edit this file as you like. 2 | # 3 | # All these sections are optional. Each section with the exception of [general] represents 4 | # one rule and each key in it is an option for that specific rule. 5 | # 6 | # Rules and sections can be referenced by their full name or by id. For example 7 | # section "[body-max-line-length]" could be written as "[B1]". Full section names are 8 | # used in here for clarity. 9 | # 10 | [general] 11 | # Ignore certain rules, this example uses both full name and id 12 | # ignore=title-trailing-punctuation, T3 13 | 14 | # verbosity should be a value between 1 and 3, the commandline -v flags take precedence over this 15 | # verbosity = 2 16 | 17 | # By default gitlint will ignore merge, revert, fixup and squash commits. 18 | # ignore-merge-commits=true 19 | # ignore-revert-commits=true 20 | # ignore-fixup-commits=true 21 | # ignore-squash-commits=true 22 | 23 | # Ignore any data send to gitlint via stdin 24 | # ignore-stdin=true 25 | 26 | # Fetch additional meta-data from the local repository when manually passing a 27 | # commit message to gitlint via stdin or --commit-msg. Disabled by default. 28 | # staged=true 29 | 30 | # Enable debug mode (prints more output). Disabled by default. 31 | # debug=true 32 | 33 | # Enable community contributed rules 34 | # See http://jorisroovers.github.io/gitlint/contrib_rules for details 35 | 36 | # Set the extra-path where gitlint will search for user defined rules 37 | # See http://jorisroovers.github.io/gitlint/user_defined_rules for details 38 | extra-path=gitlint 39 | 40 | # This is an example of how to configure the "title-max-length" rule and 41 | # set the line-length it enforces to 80 42 | [title-max-length] 43 | line-length=80 44 | 45 | # [title-must-not-contain-word] 46 | # Comma-separated list of words that should not occur in the title. Matching is case 47 | # insensitive. It's fine if the keyword occurs as part of a larger word (so "WIPING" 48 | # will not cause a violation, but "WIP: my title" will. 49 | # words=wip 50 | 51 | [title-match-regex] 52 | # python like regex (https://docs.python.org/2/library/re.html) that the 53 | # commit-msg title must be matched to. 54 | # Note that the regex can contradict with other rules if not used correctly 55 | # (e.g. title-must-not-contain-word). 56 | regex=^MeTee:.* 57 | 58 | [body-max-line-length] 59 | line-length=72 60 | 61 | # [body-min-length] 62 | # min-length=5 63 | 64 | # [body-is-missing] 65 | # Whether to ignore this rule on merge commits (which typically only have a title) 66 | # default = True 67 | # ignore-merge-commits=false 68 | 69 | # [body-changed-file-mention] 70 | # List of files that need to be explicitly mentioned in the body when they are changed 71 | # This is useful for when developers often erroneously edit certain files or git submodules. 72 | # By specifying this rule, developers can only change the file when they explicitly reference 73 | # it in the commit message. 74 | # files=gitlint/rules.py,README.md 75 | 76 | [author-valid-email] 77 | # python like regex (https://docs.python.org/2/library/re.html) that the 78 | # commit author email address should be matched to 79 | # For example, use the following regex if you only want to allow email addresses from foo.com 80 | regex=[^@]+@(?!localhost).*$ 81 | 82 | # [ignore-by-title] 83 | # Ignore certain rules for commits of which the title matches a regex 84 | # E.g. Match commit titles that start with "Release" 85 | # regex=^Release(.*) 86 | 87 | # Ignore certain rules, you can reference them by their id or by their full name 88 | # Use 'all' to ignore all rules 89 | # ignore=T1,body-min-length 90 | 91 | # [ignore-by-body] 92 | # Ignore certain rules for commits of which the body has a line that matches a regex 93 | # E.g. Match bodies that have a line that that contain "release" 94 | # regex=(.*)release(.*) 95 | # 96 | # Ignore certain rules, you can reference them by their id or by their full name 97 | # Use 'all' to ignore all rules 98 | # ignore=T1,body-min-length 99 | 100 | # This is a contrib rule - a community contributed rule. These are disabled by default. 101 | # You need to explicitly enable them one-by-one by adding them to the "contrib" option 102 | # under [general] section above. 103 | # [contrib-title-conventional-commits] 104 | # Specify allowed commit types. For details see: https://www.conventionalcommits.org/ 105 | # types = bugfix,user-story,epic 106 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [5.0.0] 2 | 3 | **Note:** Backward incompatible API change: 4 | The HECI_DEVICE_KIND_* enums and kind field in struct tee_device_address 5 | are renamed to HECI_HW_TYPE_* and hw_type field to avoid clash with 6 | device kind value provided by OS drivers. 7 | 8 | ### Changed 9 | - EFI: Decrease HW register polling timeout 10 | - EFI: Refactor HECI_DEVICE_KIND 11 | - Linux: pull libmei 1.6.4 12 | 13 | ### Fixed 14 | - EFI: Change propertyMap array type to CHAR8* 15 | - EFI: Fixing compilation errors with GCC 16 | - account for old Windows driver 17 | 18 | ### Added 19 | - CMake: Windows: add release 64 static preset 20 | - Add cpp wrapper 21 | - TeeGetKind API 22 | 23 | ## [4.3.1] 24 | 25 | ### Fixed 26 | - Windows: fix asan build 27 | 28 | ### Changed 29 | - doc: update Doxygen template 30 | 31 | ## [4.3.0] 32 | 33 | ### Fixed 34 | - Windows: process access denied on open 35 | - UEFI: Add driver logic for fixed clients 36 | 37 | ### Added 38 | - Windows: add resource 39 | - cmake: add 32 bit release preset 40 | - add getters for maxMsgLen and prtocolVer 41 | 42 | ## [4.2.1] 43 | 44 | ### Fixed 45 | - EFI: fix open multiple connections to the different clients 46 | - Linux: import libmei 1.6.3: fix for traffic dump in release mode and build on 32bit Linux. 47 | 48 | ## [4.2.0] 49 | 50 | **Note:** ABI breakage in this version, struct tee_device_address was expanded 51 | 52 | ### Fixed 53 | - tests: make tests robust 54 | - Linux: fix variable type 55 | - Windows: init read/write timeout to INT_MAX 56 | - tests: add connect retries 57 | 58 | ### Added 59 | - samples: add basic sample 60 | - UEFI: initial implementation 61 | - CMake: Windows: add static build 62 | 63 | ### Changed 64 | - Linux: pull libmei 1.6.1 65 | - CMake: minimum CMake to 3.15 and fix static build 66 | 67 | ## [4.1.0] 68 | 69 | ### Fixed 70 | - Linux: add newlines to messages 71 | - Linux: cancel waiting operation on disconnect 72 | - Windows: rewrite overlapped operations 73 | - Linux: define GUID in more compatible way 74 | - tests: fix GetDriverVersion test 75 | - tests: fix crash in failed 1000 handles test 76 | - Windows: do not retake last error from ioctl 77 | - Windows: demote print to debug 78 | - CMake: use PDB path generator expression 79 | - Linux: fix timeout and signedness 80 | 81 | ### Added 82 | - README: add thread safety section 83 | - tests: add test for interrupted read 84 | - CMake: enable several extended compilation warnings 85 | 86 | ### Changed 87 | - Linux: pull libmei 1.6.0 88 | 89 | ### Removed 90 | - Linux: drop unused define 91 | - Windows: remove unused layers 92 | - Doxygen: disable HTML timestamps 93 | 94 | ## [4.0.0] 95 | 96 | **Note:** Backward compatible API change 97 | 98 | ### Fixed 99 | - Windows: initilaize variables 100 | - conan: support higher version of the Linux compilers 101 | - linux: fix print in get handle 102 | - linux: do not set log if init failed 103 | - Windows: fix close on exit 104 | - Windows: add missing newline 105 | - samples: return log level to original 106 | - Linux: fix timeout treatment 107 | - tests: disconnect at the end of test 108 | - log: demote FUNC_ENTRY/EXIT to debug 109 | 110 | ### Added 111 | - add CONTRIBUTING.md file 112 | - add GetTRC API 113 | - add init api with all parameters 114 | - add option for log callback 115 | - git: add full VS gitignore 116 | - CMake: add preset for full debug build 117 | 118 | ### Changed 119 | - Linux: pull libmei 1.5.6 120 | - samples: use stdbool on windows 121 | - windows: replace spaces with tabs 122 | 123 | ### Removed 124 | - CMake: disable doc build by default 125 | - CMake: drop system ver requirement 126 | 127 | ## [3.2.4] 128 | 129 | ### Fixed 130 | - Linux: pull in libmei 1.5.4 with reconnect-on-error fix 131 | 132 | ### Added 133 | - README: add nproc explanation, refine grammar and formatting 134 | 135 | ## [3.2.3] 136 | 137 | ### Fixed 138 | - tests: fix windows tests 139 | - README: update Windows build instructions 140 | 141 | ## [3.2.2] 142 | 143 | ### Fixed 144 | - Linux: fix return value treatment of mei_set_log_level 145 | 146 | ## [3.2.1] 147 | 148 | ### Added 149 | - set security policy for the project 150 | 151 | ### Fixed 152 | - Windows: fix wrong return status 153 | - Windows: move to_int inline function to metee_win.h 154 | - Windows: remove unused labels 155 | 156 | ## [3.2.0] 157 | 158 | ### Added 159 | - Linux: pull in libmei 1.5.3 160 | - implement log level APIs 161 | - Windows: remove redundant function WaitForOperationEnd 162 | - Windows: add license for MSFT WDK samples 163 | 164 | ## [3.1.6] 165 | 166 | ### Fixed 167 | - CMake: fix secure compiler options 168 | - Windows: convert win32 errors to library errors 169 | - doc: update doxygen config 170 | - Linux: pull in libmei 1.5.2 171 | - Windows: return with error on memcpy failure 172 | - Windows: Drop non needed variable initialization on declaration 173 | 174 | ### Added 175 | - CMake: add preset to compile all code 176 | 177 | ## [3.1.5] 178 | 179 | ### Fixed 180 | - Linux: return better errors from TeeInit 181 | - samples: mkhi: account for errors from init 182 | - tests: update tests for fixed linux init 183 | 184 | ## [3.1.4] 185 | 186 | ### Fixed 187 | - Linux: replace select with poll 188 | - Linux: use positive errno number in strerror 189 | - conan: drop cxx requirement 190 | 191 | ### Changed 192 | - build: take gtest 1.12.1 193 | - tests: use fixed gtest version in download 194 | 195 | ### Added 196 | - CMake: add Windows presets 197 | - test: add test for big file descriptor 198 | 199 | ## [3.1.3] 200 | 201 | ### Fixed 202 | - samples: fix assignment and add explicit type-cast 203 | - Linux: pull-in libmei 1.5.1 with fix for reconnect if client not found 204 | 205 | ## [3.1.2] 206 | 207 | ### Fixed 208 | 209 | - tests: fix gtest branch name 210 | - CHANGELOG: fix the indentation 211 | 212 | ## [3.1.1] 213 | 214 | ### Fixed 215 | 216 | - Windows: push DebugPrint down 217 | - Windows: tests: disable pending write test on Windows 218 | - doc: add missing return values documentation 219 | 220 | ### Changed 221 | 222 | - CMake: make docs optional 223 | 224 | 225 | ## [3.1.0] 226 | 227 | **Note:** Backward compatible API change 228 | 229 | ### Added 230 | 231 | - Add TEE_PERMISSION_DENIED error code 232 | - Add stress tests 233 | 234 | ## [3.0.1] 235 | 236 | ### Added 237 | - add SPDX license also on .cmake-format config file 238 | - samples: add GSC sample 239 | - Build: add conan packaging. 240 | 241 | ## Fixed 242 | - test: initialize deviceHandle in constructor 243 | - README.md and more verbose description 244 | - CMake: add secure compile and link flag 245 | 246 | ## [3.0.0] 247 | 248 | **Note:** below changes break API and ABI compatibility with older library versions. 249 | 250 | ### Changed 251 | - Windows: Add separate TeeInitGUID API to init library by using device class GUID. 252 | 253 | ### Fixed 254 | - Fix miscellaneous code issues in samples. 255 | - Windows: return right size of processed data. 256 | - Windows: fix connect to the externally provided guid. 257 | - Windows: enlarge debug output buffer. 258 | - Modernize CMake configuration. 259 | - Fix spelling mistakes all over the library. 260 | - Windows: check return pointers for NULL before write. 261 | - Windows: fix reconnect if underlying client was disconnected from FW side. 262 | - Doxygen documentation cleaned up and expanded. 263 | - Linux: import libmei 1.4 code. 264 | 265 | ### Added 266 | - Windows: ability to connect to device by path. 267 | - API to use externally opened file handle. 268 | - Tests with long buffers. 269 | - Ability to build dynamic library. 270 | - Support for meson build system. 271 | - Option to write output to console instead of Syslog/DbgView 272 | 273 | ## [2.2.2] 274 | 275 | ### Added 276 | 277 | ### Changed 278 | 279 | ### Fixed 280 | - Windows: fix package target in cmake. 281 | 282 | ## [2.2.1] 283 | 284 | ### Added 285 | - Enable gitlint, cmake-format, codespell checking. 286 | - Added .gitattributes. 287 | 288 | ### Changed 289 | - Reformat cmake files 290 | - Update .gitignore 291 | - convert CHANGELOG to Markdown format 292 | 293 | ### Fixed 294 | - Add -D_GNU_SOURCE for strdup and other functions. 295 | - Fix spelling errors in the library. 296 | - Windows: enlarge debug output buffer. 297 | - Windows: return right size of processed data. 298 | - Windows: fix connect to the externally provided guid. 299 | - Fix debug print. 300 | - Fix miscellaneous code issues. 301 | 302 | 303 | ## [2.2.0] 304 | 305 | ### Added 306 | - API to retrieve FW status registers 307 | 308 | ### Changed 309 | 310 | ### Fixed 311 | 312 | 313 | ## [2.1.1] 314 | 315 | ### Added 316 | - Add tests and samples to install package. 317 | 318 | ### Changed 319 | - Linux: Set default device to /dev/mei0 as all modern Linux kernels sports /dev/meiX char device nodes. 320 | 321 | ### Fixed 322 | - Linux: include select.h to fix build with musl libc. 323 | 324 | 325 | ## [2.1.0] 326 | 327 | ### Added 328 | - Add DEFINE_GUID macro in Linux header. 329 | 330 | ### Changed 331 | - Use name GUID in all OSs. 332 | 333 | ### Fixed 334 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright (C) 2014-2024 Intel Corporation 3 | cmake_minimum_required(VERSION 3.15) 4 | cmake_policy(SET CMP0091 NEW) 5 | project(metee) 6 | 7 | option(BUILD_DOCS "Build docs" NO) 8 | option(BUILD_TEST "Build self-test" NO) 9 | option(BUILD_SAMPLES "Build samples" NO) 10 | option(BUILD_MSVC_RUNTIME_STATIC "Build with static runtime libraries on MSVC" 11 | NO 12 | ) 13 | option(BUILD_SHARED_LIBS "Build shared library" NO) 14 | option(CONSOLE_OUTPUT "Push debug and error output to console (instead of syslog)" NO) 15 | 16 | include(GNUInstallDirs) 17 | 18 | set(LICENSE Apache) 19 | include(version.cmake) 20 | 21 | if(WIN32) 22 | include(win32.cmake) 23 | else(WIN32) 24 | include(linux.cmake) 25 | endif(WIN32) 26 | 27 | set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER include/metee.h) 28 | set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${TEE_VERSION_STRING}) 29 | set_target_properties( 30 | ${PROJECT_NAME} PROPERTIES SOVERSION ${TEE_VERSION_STRING} 31 | ) 32 | set_target_properties(${PROJECT_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) 33 | 34 | target_include_directories(${PROJECT_NAME} PUBLIC include) 35 | 36 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") 37 | set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG") 38 | 39 | install( 40 | TARGETS ${PROJECT_NAME} 41 | ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" 42 | LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" 43 | RUNTIME DESTINATION "${CMAKE_INSTALL_LIBDIR}" 44 | PUBLIC_HEADER DESTINATION include 45 | ) 46 | 47 | # Documentation 48 | if(BUILD_DOCS) 49 | find_package(Doxygen) 50 | if(DOXYGEN_FOUND) 51 | set(DOXYGEN_INPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 52 | set(DOXYGEN_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 53 | configure_file( 54 | ${CMAKE_CURRENT_SOURCE_DIR}/include/Doxyfile.in 55 | ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY 56 | ) 57 | 58 | add_custom_target( 59 | doc ALL 60 | ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 61 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 62 | COMMENT "Generating documentation with Doxygen" 63 | VERBATIM 64 | ) 65 | 66 | if(UNIX) 67 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/man/man3 68 | DESTINATION ${CMAKE_INSTALL_MANDIR} 69 | ) 70 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html 71 | DESTINATION ${CMAKE_INSTALL_DOCDIR} 72 | ) 73 | else() 74 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION doc) 75 | endif() 76 | endif() 77 | endif() 78 | 79 | # CPack 80 | set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) 81 | set(CPACK_PACKAGE_VERSION_MAJOR ${TEE_VERSION_MAJOR}) 82 | set(CPACK_PACKAGE_VERSION_MINOR ${TEE_VERSION_MINOR}) 83 | set(CPACK_PACKAGE_VERSION_PATCH ${TEE_VERSION_PATCH}) 84 | set(CPACK_PACKAGE_VENDOR "Intel, Inc") 85 | set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "ME TEE Interface Library") 86 | set(CPACK_PACKAGE_CONTACT "linux-mei@linux.intel.com") 87 | set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/DESCRIPTION) 88 | set(CPACK_SOURCE_GENERATOR "TBZ2;ZIP") 89 | set(CPACK_SOURCE_PACKAGE_FILE_NAME ${PROJECT_NAME}-${TEE_VERSION_STRING}) 90 | add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source) 91 | 92 | # RPM Specific 93 | set(CPACK_RPM_PACKAGE_RELEASE 1) 94 | set(CPACK_RPM_PACKAGE_LICENSE ${LICENSE}) 95 | set(CPACK_RPM_PACKAGE_GROUP "Development") 96 | 97 | # Debian Specific 98 | set(CPACK_DEBIAN_PACKAGE_VERSION 1) 99 | set(CPACK_DEBIAN_PACKAGE_SECTION "devel") 100 | 101 | if(UNIX) 102 | set(CPACK_GENERATOR "TGZ") 103 | 104 | find_program(RPM_EXE rpmbuild) 105 | if(RPM_EXE) 106 | list(APPEND CPACK_GENERATOR "RPM") 107 | endif(RPM_EXE) 108 | 109 | find_program(DEB_EXE debuild) 110 | if(DEB_EXE) 111 | list(APPEND CPACK_GENERATOR "DEB") 112 | endif(DEB_EXE) 113 | else(UNIX) 114 | set(CPACK_GENERATOR "ZIP") 115 | endif(UNIX) 116 | 117 | include(CPack) 118 | 119 | if(BUILD_TEST) 120 | add_subdirectory(tests) 121 | endif(BUILD_TEST) 122 | if(BUILD_SAMPLES) 123 | add_subdirectory(samples) 124 | endif(BUILD_SAMPLES) 125 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "configurePresets": [ 4 | { 5 | "name": "base64", 6 | "displayName": "Windows x86-64 base", 7 | "description": "Build x86-64 Release, VS2019", 8 | "hidden": true, 9 | "generator": "Visual Studio 16 2019", 10 | "architecture": { 11 | "value": "x64", 12 | "strategy": "set" 13 | }, 14 | "cacheVariables": { 15 | "BUILD_SHARED_LIBS": "YES", 16 | "BUILD_MSVC_RUNTIME_STATIC": "YES" 17 | } 18 | }, 19 | { 20 | "name": "base32", 21 | "displayName": "Windows x86 base", 22 | "description": "Build x86 Release, VS2019", 23 | "hidden": true, 24 | "generator": "Visual Studio 16 2019", 25 | "architecture": { 26 | "value": "Win32", 27 | "strategy": "set" 28 | }, 29 | "cacheVariables": { 30 | "BUILD_SHARED_LIBS": "YES", 31 | "BUILD_MSVC_RUNTIME_STATIC": "YES" 32 | } 33 | }, 34 | { 35 | "name": "Debug32AllStatic", 36 | "displayName": "Windows x86 Debug Static All", 37 | "description": "Build x86 Debug, VS2019, including test and samples", 38 | "inherits": "base32", 39 | "binaryDir": "${sourceDir}/Debug", 40 | "cacheVariables": { 41 | "CMAKE_BUILD_TYPE": "Debug", 42 | "BUILD_TEST": "YES", 43 | "BUILD_SAMPLES": "YES", 44 | "BUILD_SHARED_LIBS": "NO" 45 | } 46 | }, 47 | { 48 | "name": "Release32AllStatic", 49 | "displayName": "Windows x86 Release Static All", 50 | "description": "Build x86 Release, VS2019, including test and samples", 51 | "inherits": "base32", 52 | "binaryDir": "${sourceDir}/Release", 53 | "cacheVariables": { 54 | "CMAKE_BUILD_TYPE": "Release", 55 | "BUILD_TEST": "YES", 56 | "BUILD_SAMPLES": "YES", 57 | "BUILD_SHARED_LIBS": "NO" 58 | } 59 | }, 60 | { 61 | "name": "Release32Static", 62 | "displayName": "Windows x86 Release Static", 63 | "description": "Build x86 Release, VS2019", 64 | "inherits": "base32", 65 | "binaryDir": "${sourceDir}/Release", 66 | "cacheVariables": { 67 | "CMAKE_BUILD_TYPE": "Release", 68 | "BUILD_SHARED_LIBS": "NO" 69 | } 70 | }, 71 | { 72 | "name": "Release32", 73 | "displayName": "Windows x86 Release", 74 | "description": "Build x86 Release, VS2019", 75 | "inherits": "base32", 76 | "binaryDir": "${sourceDir}/Release", 77 | "cacheVariables": { 78 | "CMAKE_BUILD_TYPE": "Release" 79 | } 80 | }, 81 | { 82 | "name": "Release64", 83 | "displayName": "Windows x86-64 Release", 84 | "description": "Build x86-64 Release, VS2019", 85 | "inherits": "base64", 86 | "binaryDir": "${sourceDir}/Release", 87 | "cacheVariables": { 88 | "CMAKE_BUILD_TYPE": "Release" 89 | } 90 | }, 91 | { 92 | "name": "Release64Static", 93 | "displayName": "Windows x86-64 Release Static", 94 | "description": "Build x86-64 Release, VS2019", 95 | "inherits": "base64", 96 | "binaryDir": "${sourceDir}/Release", 97 | "cacheVariables": { 98 | "CMAKE_BUILD_TYPE": "Release", 99 | "BUILD_SHARED_LIBS": "NO" 100 | } 101 | }, 102 | { 103 | "name": "Debug64All", 104 | "displayName": "Windows x86-64 Debug All", 105 | "description": "Build x86-64 Debug, VS2019, including test and samples", 106 | "inherits": "base64", 107 | "binaryDir": "${sourceDir}/Debug", 108 | "cacheVariables": { 109 | "CMAKE_BUILD_TYPE": "Debug", 110 | "BUILD_TEST": "YES", 111 | "BUILD_SAMPLES": "YES" 112 | } 113 | } 114 | ], 115 | "buildPresets": [ 116 | { 117 | "name": "Debug32AllStatic", 118 | "configurePreset": "Debug32AllStatic", 119 | "configuration": "Debug" 120 | }, 121 | { 122 | "name": "Release32AllStatic", 123 | "configurePreset": "Release32AllStatic", 124 | "configuration": "Release" 125 | }, 126 | { 127 | "name": "Release32Static", 128 | "configurePreset": "Release32Static", 129 | "configuration": "Release" 130 | }, 131 | { 132 | "name": "Release32", 133 | "configurePreset": "Release32", 134 | "configuration": "Release" 135 | }, 136 | { 137 | "name": "Release64", 138 | "configurePreset": "Release64", 139 | "configuration": "Release" 140 | }, 141 | { 142 | "name": "Release64Static", 143 | "configurePreset": "Release64Static", 144 | "configuration": "Release" 145 | }, 146 | { 147 | "name": "Debug64All", 148 | "configurePreset": "Debug64All", 149 | "configuration": "Debug" 150 | } 151 | ] 152 | } 153 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ### License 4 | 5 | MeTee library is licensed under the terms in [LICENSE](COPYING). 6 | By contributing to the project, you agree to the license and copyright 7 | terms therein and release your contribution under these terms. 8 | 9 | ### Git Commit Messages 10 | 11 | ### A properly formed git commit subject line should always be able to complete the following sentence 12 | If applied, this commit will *\* 13 | 14 | ### Rules for a great git commit message style 15 | 16 | * Separate subject from body with a blank line. 17 | * Do not end the subject line with a period, it will disturb the patch creation. 18 | * Capitalize each paragraph. 19 | * Use the imperative mood. 20 | * Wrap lines at 72 character.s 21 | * Use the body to explain what and why you have done something, 22 | if change is complex also explain how. 23 | 24 | ### Information in commit messages 25 | 26 | * Describe why a change is being made. 27 | * How does it address the issue? 28 | * What effects does the patch have? 29 | * Do not assume the reviewer understands what the original problem was. 30 | * Do not assume the code is self-evident/self-documenting. 31 | * Read the commit message to see if it hints at improved code structure. 32 | * The first commit line is the most important. 33 | * Describe any limitations of the current code. 34 | * Do not include patch set-specific comments. 35 | 36 | Details for each point and good commit message examples can be found on https://wiki.openstack.org/wiki/GitCommitMessages#Information_in_commit_messages 37 | 38 | ### References in commit messages 39 | 40 | * Structure: 41 | ``` 42 | MeTee: : 43 | <blank line> 44 | <body> 45 | Signed-off-by: Your Name <your.email@yyy.zzz> 46 | ``` 47 | * Possible subsection 48 | - github: changes in github management: all under .github/ 49 | - Linux: Linux os specific changes. 50 | - Windows: Windows os specific changes. 51 | - CMake: changes in the cmake build configuration. 52 | - tests: changes in tests. 53 | - samples: changes in samples. 54 | - conan: changes in conan configuration. 55 | - doc: changes in documentation. 56 | 57 | ### Sign your work 58 | 59 | Please use the sign-off line at the end of the patch. Your signature 60 | certifies that you wrote the patch or otherwise have the right to pass 61 | it on as an open-source patch. The rules are pretty simple: if you can 62 | certify the below 63 | (from [developercertificate.org](http://developercertificate.org/)): 64 | 65 | 66 | ``` 67 | Developer Certificate of Origin 68 | Version 1.1 69 | 70 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 71 | 660 York Street, Suite 102, 72 | San Francisco, CA 94110 USA 73 | 74 | Everyone is permitted to copy and distribute verbatim copies of this 75 | license document, but changing it is not allowed. 76 | 77 | Developer's Certificate of Origin 1.1 78 | 79 | By making a contribution to this project, I certify that: 80 | 81 | (a) The contribution was created in whole or in part by me and I 82 | have the right to submit it under the open source license 83 | indicated in the file; or 84 | 85 | (b) The contribution is based upon previous work that, to the best 86 | of my knowledge, is covered under an appropriate open source 87 | license and I have the right under that license to submit that 88 | work with modifications, whether created in whole or in part 89 | by me, under the same open source license (unless I am 90 | permitted to submit under a different license), as indicated 91 | in the file; or 92 | 93 | (c) The contribution was provided directly to me by some other 94 | person who certified (a), (b) or (c) and I have not modified 95 | it. 96 | 97 | (d) I understand and agree that this project and the contribution 98 | are public and that a record of the contribution (including all 99 | personal information I submit with it, including my sign-off) is 100 | maintained indefinitely and may be redistributed consistent with 101 | this project or the open source license(s) involved. 102 | ``` 103 | 104 | Then you just add a line to every git commit message: 105 | 106 | Signed-off-by: Joe Smith <joe.smith@email.com> 107 | 108 | Use your real name (sorry, no pseudonyms or anonymous contributions.) 109 | 110 | If you set your `user.name` and `user.email` git configs, you can sign your 111 | commit automatically with `git commit -s`. 112 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | # MeTee library 2 | 3 | MeTee library provides a cross-platform simple programming interface for accessing 4 | Intel HECI interfaces on devices found in BigCore and Atom based products. 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Intel(R) ME TEE Library 2 | 3 | ME TEE Library is a C library to access CSE/CSME/GSC firmware via a mei interface. 4 | ME TEE provides a single cross-platform API to access to MEI devices on Linux and Windows. 5 | MEI TEE API simplify connection and communication with the mei device, and firmware status 6 | registers retrieval. 7 | 8 | ## CMake Build 9 | 10 | ME TEE library uses CMake for both Linux and Windows builds. 11 | 12 | ### Windows 13 | 14 | From the "Developer Command Prompt for VS 2019" with C compiler and CMake component installed: 15 | 16 | 1. Go to sources directory: `cd <srcdir>` 17 | 2. Create `build` directory: `mkdir build` 18 | 3. Run `cmake -G "Visual Studio 16 2019" -A <build_arch> <srcdir>` from the `build` directory (best to set *build_arch* to Win32) 19 | 4. Run `cmake --build . --config Release --target package -j <nproc>` from the `build` directory to build an archive with all executables and libraries, *nproc* is the number of parallel threads in compilation, best to set to number of processor threads available 20 | 21 | By default, CMake links with dynamic runtime (/MD), set BUILD_MSVC_RUNTIME_STATIC to ON to link with static runtime (/MT): 22 | `cmake -G "Visual Studio 16 2019" -A <build_arch> -DBUILD_MSVC_RUNTIME_STATIC=ON <srcdir>` 23 | 24 | ### Linux 25 | 26 | 1. Create `build` directory 27 | 2. Run `cmake <srcdir>` from the `build` directory 28 | 3. Run `make -j$(nproc) package` from the `build` directory to build .deb and .rpm packages and .tgz archive 29 | 30 | 31 | ## Meson Build 32 | 33 | ME TEE library also supports Meson for both Linux and Windows builds. 34 | 35 | ### General Setup 36 | 37 | ```sh 38 | meson setup build/ 39 | meson configure -Dbuildtype=debug/release build 40 | ninja -v -C build/ 41 | ``` 42 | 43 | ### Windows Visual Studio 44 | 45 | In order to use Visual Studio project meson requires to run under Visual Studio Command Prompt. 46 | In case of Visual Studio 2019, you can use either *"x64 Native Tools Command Prompt for VS 2019"* 47 | or under powershell enter VisualStudio DevShell and then just continue with the [general setup](#general-setup) 48 | 49 | #### Powershell example setting: 50 | 51 | ```powershell 52 | $installPath = &"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -version 16.0 -property installationpath 53 | Import-Module (Join-Path $installPath "Common7\Tools\Microsoft.VisualStudio.DevShell.dll") 54 | Enter-VsDevShell -VsInstallPath $installPath -SkipAutomaticLocation 55 | ``` 56 | 57 | ## Thread safety 58 | 59 | The library supports multithreading but is not thread-safe. 60 | Every thread should either initialize and use its own handle 61 | or a locking mechanism should be implemented by the caller to ensure 62 | that only one thread uses the handle at any time. 63 | The only exception is ability to call Disconnect to exit from read 64 | blocked on another thread. -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | Intel is committed to rapidly addressing security vulnerabilities affecting our customers and providing clear guidance on the solution, impact, severity and mitigation. 4 | 5 | ## Supported Versions 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | 3.1.0 | :white_check_mark: | 10 | | < 3.1.0 | :x: | 11 | 12 | ## Reporting a Vulnerability 13 | 14 | Please report any security vulnerabilities in this project [utilizing the guidelines here](https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html). 15 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 5.0.0 2 | -------------------------------------------------------------------------------- /conanfile.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright (C) 2020-2023 Intel Corporation 3 | from conans import ConanFile, CMake, tools 4 | from conans.tools import load 5 | from conans.model.version import Version 6 | import os 7 | 8 | class MeteeConan(ConanFile): 9 | name = "metee" 10 | license = "SPDX-License-Identifier: Apache-2.0" 11 | url = "https://github.com/intel/metee" 12 | description = "Cross-platform access library for Intel(R) CSME HECI interface." 13 | settings = "os", "compiler", "build_type", "arch" 14 | options = {"shared": [True, False]} 15 | default_options = {"shared": False} 16 | generators = "cmake", "visual_studio" 17 | exports_sources = "*" 18 | 19 | def configure(self): 20 | del self.settings.compiler.libcxx 21 | 22 | def package_id(self): 23 | v = Version(str(self.settings.compiler.version)) 24 | if self.settings.compiler == "gcc" and (v >= "6" and v <= "12"): 25 | self.info.settings.compiler.version = "GCC version between 6 and 12" 26 | if self.settings.compiler == "clang" and (v >= "6" and v <= "15"): 27 | self.info.settings.compiler.version = "clang version between 6 and 15" 28 | 29 | def set_version(self): 30 | content = load(os.path.join(self.recipe_folder, "VERSION")) 31 | self.version = content 32 | 33 | def _configure_cmake(self): 34 | cmake = CMake(self) 35 | if self.settings.os == "Windows" and "MT" in self.settings.compiler.runtime: 36 | cmake.definitions["BUILD_MSVC_RUNTIME_STATIC"]="on" 37 | cmake.configure(source_folder="") 38 | return cmake 39 | 40 | def build(self): 41 | cmake = self._configure_cmake() 42 | cmake.build() 43 | 44 | def package(self): 45 | cmake = self._configure_cmake() 46 | cmake.install() 47 | 48 | def package_info(self): 49 | self.cpp_info.components["libmetee"].libs = ["metee"] 50 | -------------------------------------------------------------------------------- /get-version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # SPDX-License-Identifier: Apache-2.0 3 | # Copyright (C) 2020 Intel Corporation 4 | 5 | def get_ver(): 6 | ''' Obtain version string from VERSION file ''' 7 | with open('VERSION') as the_fd: 8 | return the_fd.readline() 9 | 10 | if __name__ == '__main__': 11 | 12 | version = get_ver() 13 | print(version) 14 | -------------------------------------------------------------------------------- /gitlint/rules.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # Copyright (C) 2020 Intel Corporation 3 | 4 | from gitlint.rules import CommitRule, RuleViolation 5 | from gitlint.options import IntOption, ListOption 6 | from gitlint import utils 7 | 8 | 9 | class BodyMinLineCount(CommitRule): 10 | name = "body-min-line-count" 11 | 12 | # A rule MUST have a *unique* id, we recommend starting with UC (for User-defined Commit-rule). 13 | id = "UC1" 14 | 15 | options_spec = [IntOption('min-line-count', 1, "Minimum body line count excluding Signed-off-by")] 16 | 17 | def validate(self, commit): 18 | filtered = [x for x in commit.message.body if not x.lower().startswith("signed-off-by") and x != ''] 19 | line_count = len(filtered) 20 | min_line_count = self.options['min-line-count'].value 21 | if line_count < min_line_count: 22 | message = "Body has no content, should at least have {} line.".format(min_line_count) 23 | return [RuleViolation(self.id, message, line_nr=1)] 24 | 25 | class SignedOffBy(CommitRule): 26 | """ This rule will enforce that each commit contains a "Signed-off-by:" line. 27 | We keep things simple here and just check whether the commit body contains a line that starts with "Signed-off-by:". 28 | """ 29 | 30 | name = "body-requires-signed-off-by" 31 | 32 | # A rule MUST have a *unique* id, we recommend starting with UC (for User-defined Commit-rule). 33 | id = "UC2" 34 | 35 | def validate(self, commit): 36 | for line in commit.message.body: 37 | if line.startswith("Signed-off-by:"): 38 | return 39 | 40 | return [RuleViolation(self.id, "Body does not contain a 'Signed-off-by' line", line_nr=1)] 41 | 42 | -------------------------------------------------------------------------------- /include/helpers.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2014-2024 Intel Corporation 4 | */ 5 | #ifndef __HELPERS_H 6 | #define __HELPERS_H 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #ifdef _WIN32 12 | #include <windows.h> 13 | #include <stdio.h> 14 | #include <stdarg.h> 15 | #include "metee.h" 16 | 17 | #if _DEBUG 18 | #define TEE_DEFAULT_LOG_LEVEL TEE_LOG_LEVEL_VERBOSE 19 | #else 20 | #define TEE_DEFAULT_LOG_LEVEL TEE_LOG_LEVEL_QUIET 21 | #endif 22 | #define DEBUG_PRINT_ME_PREFIX_EXTERNAL "TEELIB: (%s:%s():%d) " 23 | #define DEBUG_PRINT_ME_PREFIX_INTERNAL "TEELIB: (%s:%s():%d) " 24 | 25 | #define MALLOC(X) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, X) 26 | #define FREE(X) {if(X) { HeapFree(GetProcessHeap(), 0, X); X = NULL ; } } 27 | 28 | #define DEBUG_MSG_LEN 1024 29 | 30 | void DebugPrintMe(const char* args, ...); 31 | 32 | #define ErrorPrintMe(fmt, ...) DebugPrintMe(fmt, __VA_ARGS__) 33 | #define IS_HANDLE_INVALID(h) (NULL == h || 0 == h->handle || INVALID_HANDLE_VALUE == h->handle) 34 | #define INIT_STATUS TEE_INTERNAL_ERROR 35 | #elif defined(EFI) 36 | #define DEBUG_PRINT_ME_PREFIX_INTERNAL "TEELIB: (%a:%a():%d) " 37 | #define DEBUG_PRINT_ME_PREFIX_EXTERNAL "TEELIB: (%s:%s():%d) " 38 | #define DebugPrintMe(fmt, ...) AsciiPrint(fmt, ##__VA_ARGS__) 39 | #define ErrorPrintMe(fmt, ...) AsciiPrint(fmt, ##__VA_ARGS__) 40 | #else 41 | #define DEBUG_PRINT_ME_PREFIX_INTERNAL "TEELIB: (%s:%s():%d) " 42 | #define DEBUG_PRINT_ME_PREFIX_EXTERNAL "TEELIB: (%s:%s():%d) " 43 | #ifdef ANDROID 44 | // For debugging 45 | //#define LOG_NDEBUG 0 46 | #define LOG_TAG "metee" 47 | #include <cutils/log.h> 48 | #define DebugPrintMe(fmt, ...) ALOGV_IF(true, fmt, ##__VA_ARGS__) 49 | #define ErrorPrintMe(fmt, ...) ALOGE_IF(true, fmt, ##__VA_ARGS__) 50 | 51 | #ifdef LOG_NDEBUG 52 | #define TEE_DEFAULT_LOG_LEVEL TEE_LOG_LEVEL_VERBOSE 53 | #else 54 | #define TEE_DEFAULT_LOG_LEVEL TEE_LOG_LEVEL_QUIET 55 | #endif 56 | #else /* LINUX */ 57 | #ifdef SYSLOG 58 | #include <syslog.h> 59 | #define DebugPrintMe(fmt, ...) syslog(LOG_DEBUG, fmt, ##__VA_ARGS__) 60 | #define ErrorPrintMe(fmt, ...) syslog(LOG_ERR, fmt, ##__VA_ARGS__) 61 | #else 62 | #include <stdlib.h> 63 | #define DebugPrintMe(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) 64 | #define ErrorPrintMe(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) 65 | #endif /* SYSLOG */ 66 | 67 | #ifdef DEBUG 68 | #define TEE_DEFAULT_LOG_LEVEL TEE_LOG_LEVEL_VERBOSE 69 | #else 70 | #define TEE_DEFAULT_LOG_LEVEL TEE_LOG_LEVEL_QUIET 71 | #endif 72 | 73 | #endif /* ANDROID */ 74 | 75 | #define MALLOC(X) malloc(X) 76 | #define FREE(X) { if(X) { free(X); X = NULL ; } } 77 | 78 | #define IS_HANDLE_INVALID(h) (NULL == h || 0 == h->handle || -1 == h->handle) 79 | #define INIT_STATUS -EPERM 80 | #endif /* _WIN32 */ 81 | 82 | #define DBGPRINT(h, _x_, ...) \ 83 | if ((h) && (h)->log_level >= TEE_LOG_LEVEL_VERBOSE) { \ 84 | if ((h)->log_callback) \ 85 | (h)->log_callback(false, DEBUG_PRINT_ME_PREFIX_EXTERNAL _x_,__FILE__,__FUNCTION__,__LINE__, ##__VA_ARGS__); \ 86 | else \ 87 | DebugPrintMe(DEBUG_PRINT_ME_PREFIX_INTERNAL _x_,__FILE__,__FUNCTION__,__LINE__, ##__VA_ARGS__); \ 88 | } 89 | 90 | #define ERRPRINT(h, _x_, ...) \ 91 | if ((h) && (h)->log_level >= TEE_LOG_LEVEL_ERROR) { \ 92 | if ((h)->log_callback) \ 93 | (h)->log_callback(true, DEBUG_PRINT_ME_PREFIX_EXTERNAL _x_,__FILE__,__FUNCTION__,__LINE__, ##__VA_ARGS__); \ 94 | else \ 95 | ErrorPrintMe(DEBUG_PRINT_ME_PREFIX_INTERNAL _x_,__FILE__,__FUNCTION__,__LINE__, ##__VA_ARGS__); \ 96 | } 97 | 98 | #define FUNC_ENTRY(h) DBGPRINT(h, "Entry\n") 99 | #define FUNC_EXIT(h, status) DBGPRINT(h, "Exit with status: %d\n", status) 100 | 101 | #ifdef EFI 102 | #include <Library/BaseMemoryLib.h> 103 | static inline void __tee_init_handle(PTEEHANDLE handle) { SetMem(handle, sizeof(TEEHANDLE), 0);} 104 | #else /* _WIN32, LINUX */ 105 | static inline void __tee_init_handle(PTEEHANDLE handle) { memset(handle, 0, sizeof(TEEHANDLE));} 106 | #endif /* EFI */ 107 | 108 | 109 | #ifdef __cplusplus 110 | } 111 | #endif 112 | #endif /* __HELPERS_H */ 113 | -------------------------------------------------------------------------------- /include/metee.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2014-2025 Intel Corporation 4 | */ 5 | /*! \file metee.h 6 | * \brief metee library API 7 | */ 8 | #ifndef __METEE_H 9 | #define __METEE_H 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | #include <stddef.h> 16 | #include <stdint.h> 17 | #include <stdbool.h> 18 | //! @cond suppress_warnings 19 | #ifdef _WIN32 20 | #include <Windows.h> 21 | #include <initguid.h> 22 | 23 | #ifndef METEE_DLL 24 | #define METEE_DLL_API 25 | #else /* METEE_DLL */ 26 | #ifdef METEE_DLL_EXPORT 27 | #define METEE_DLL_API __declspec(dllexport) 28 | #else 29 | #define METEE_DLL_API __declspec(dllimport) 30 | #endif /* METEE_DLL_EXPORT */ 31 | #endif /* METEE_DLL */ 32 | #define TEEAPI METEE_DLL_API __stdcall 33 | #define TEE_DEVICE_HANDLE HANDLE 34 | #define TEE_INVALID_DEVICE_HANDLE ((void*)0) 35 | 36 | #elif defined(EFI) 37 | #include <Uefi.h> 38 | #define TEEAPI 39 | #define TEE_DEVICE_HANDLE void * 40 | #define TEE_INVALID_DEVICE_HANDLE ((void*)-1) 41 | 42 | // when calling TeeInitFull 43 | // TEE_DEVICE_TYPE_BDF - HECI device Bus Device Function 44 | 45 | #else /* _WIN32 */ 46 | #ifndef METEE_DLL 47 | #define METEE_DLL_API 48 | #else /*! METEE_DLL */ 49 | #ifdef METEE_DLL_EXPORT 50 | #define METEE_DLL_API __attribute__((__visibility__("default"))) 51 | #else 52 | #define METEE_DLL_API 53 | #endif /* METEE_DLL_EXPORT */ 54 | #endif /* METEE_DLL */ 55 | #define TEEAPI METEE_DLL_API 56 | 57 | #ifndef GUID_DEFINED 58 | #define GUID_DEFINED 1 59 | typedef struct _GUID { 60 | uint32_t l; 61 | uint16_t w1; 62 | uint16_t w2; 63 | uint8_t b[8]; 64 | } GUID; 65 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 66 | const GUID name \ 67 | = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } 68 | #endif /* GUID_DEFINED */ 69 | 70 | #define TEE_DEVICE_HANDLE int 71 | #define TEE_INVALID_DEVICE_HANDLE (-1) 72 | #ifndef IN 73 | #define IN 74 | #endif 75 | #ifndef OUT 76 | #define OUT 77 | #endif 78 | #ifndef OPTIONAL 79 | #define OPTIONAL 80 | #endif 81 | #endif /* _WIN32 */ 82 | //! @endcond 83 | 84 | /*! log level 85 | */ 86 | enum tee_log_level { 87 | TEE_LOG_LEVEL_QUIET = 0, /**< no log prints */ 88 | TEE_LOG_LEVEL_ERROR = 1, /**< error log prints */ 89 | TEE_LOG_LEVEL_VERBOSE = 2, /**< verbose log prints */ 90 | TEE_LOG_LEVEL_MAX = 3, /**< upper sentinel */ 91 | }; 92 | 93 | /*! log callback function format 94 | */ 95 | typedef void(*TeeLogCallback)(bool is_error, const char* fmt, ...); 96 | 97 | /*! 98 | * Structure to store connection data 99 | */ 100 | typedef struct _TEEHANDLE { 101 | 102 | void *handle; /**< Handle to the internal structure */ 103 | size_t maxMsgLen; /**< FW Client Max Message Length */ 104 | uint8_t protcolVer; /**< FW Client Protocol FW */ 105 | enum tee_log_level log_level; /**< Log level */ 106 | TeeLogCallback log_callback; /**< Log callback */ 107 | } TEEHANDLE; 108 | 109 | /*! 110 | * \var typedestruct _TEEHANDLE *PTEEHANDLE 111 | * \brief A type definition for pointer to TEEHANDLE 112 | */ 113 | typedef TEEHANDLE *PTEEHANDLE; 114 | 115 | /*! Device address passed to the init function 116 | */ 117 | struct tee_device_address { 118 | /*! Device address type 119 | */ 120 | enum { 121 | TEE_DEVICE_TYPE_NONE = 0, /**< Select first available device */ 122 | TEE_DEVICE_TYPE_PATH = 1, /**< Use device by path (char*) */ 123 | TEE_DEVICE_TYPE_HANDLE = 2, /**< Use device by pre-opend handle */ 124 | TEE_DEVICE_TYPE_GUID = 3, /**< Select first device by GUID (Windows only) */ 125 | TEE_DEVICE_TYPE_BDF = 4, /**< Use BDF to work with HECI, EFI only */ 126 | TEE_DEVICE_TYPE_MAX = 5, /**< upper sentinel */ 127 | } type; 128 | 129 | /*! Device address */ 130 | union { 131 | const char* path; /** < Path to device */ 132 | const GUID* guid; /** Device GUID (Windows only) */ 133 | TEE_DEVICE_HANDLE handle; /**< Pre-opend handle */ 134 | struct { 135 | struct { 136 | uint32_t segment; /** HECI device Segment */ 137 | uint32_t bus; /** HECI device Bus */ 138 | uint32_t device; /** HECI device Device */ 139 | uint32_t function; /** HECI device Function */ 140 | } value; 141 | /*! Specifies HW layout: HECI, FWSTS registers locations */ 142 | enum HECI_HW_TYPE { 143 | HECI_HW_TYPE_PCH, 144 | HECI_HW_TYPE_GFX_GSC, 145 | HECI_HW_TYPE_GFX_CSC, 146 | } hw_type; /** HECI device HW type */ 147 | } bdf; 148 | } data; 149 | }; 150 | 151 | /** ZERO/NULL device handle */ 152 | #define TEEHANDLE_ZERO {0} 153 | 154 | typedef uint16_t TEESTATUS; /**< return status for API functions */ 155 | /** METEE ERROR BASE */ 156 | #define TEE_ERROR_BASE 0x0000U 157 | /** METEE SUCCESS */ 158 | #define TEE_SUCCESS (TEE_ERROR_BASE + 0) 159 | /** An internal error occurred in the library */ 160 | #define TEE_INTERNAL_ERROR (TEE_ERROR_BASE + 1) 161 | /** The device is not in the system or is not working */ 162 | #define TEE_DEVICE_NOT_FOUND (TEE_ERROR_BASE + 2) 163 | /** The device is not ready for the operation */ 164 | #define TEE_DEVICE_NOT_READY (TEE_ERROR_BASE + 3) 165 | /** An invalid parameter was used in the call */ 166 | #define TEE_INVALID_PARAMETER (TEE_ERROR_BASE + 4) 167 | /** It is not possible to complete the operation */ 168 | #define TEE_UNABLE_TO_COMPLETE_OPERATION (TEE_ERROR_BASE + 5) 169 | /** The operation has timed out */ 170 | #define TEE_TIMEOUT (TEE_ERROR_BASE + 6) 171 | /** The operation is not supported */ 172 | #define TEE_NOTSUPPORTED (TEE_ERROR_BASE + 7) 173 | /** The ME client is not present in the firmware */ 174 | #define TEE_CLIENT_NOT_FOUND (TEE_ERROR_BASE + 8) 175 | /** The device is busy */ 176 | #define TEE_BUSY (TEE_ERROR_BASE + 9) 177 | /** The ME client is not connected */ 178 | #define TEE_DISCONNECTED (TEE_ERROR_BASE + 10) 179 | /** The buffer for read not big enough */ 180 | #define TEE_INSUFFICIENT_BUFFER (TEE_ERROR_BASE + 11) 181 | /** The user don't have permission for this operation */ 182 | #define TEE_PERMISSION_DENIED (TEE_ERROR_BASE + 12) 183 | 184 | /*! Macro for successful operation result check 185 | */ 186 | #define TEE_IS_SUCCESS(Status) (((TEESTATUS)(Status)) == TEE_SUCCESS) 187 | 188 | /*! Initializes a TEE connection 189 | * \param handle A handle to the TEE device. All subsequent calls to the lib's functions 190 | * must be with this handle 191 | * \param guid GUID of the FW client that want to start a session 192 | * \param device device address structure 193 | * \param log_level log level to set (from enum tee_log_level) 194 | * \param log_callback pointer to function to run for log write, set NULL to use built-in function 195 | * \return 0 if successful, otherwise error code 196 | */ 197 | TEESTATUS TEEAPI TeeInitFull(IN OUT PTEEHANDLE handle, IN const GUID* guid, 198 | IN const struct tee_device_address device, 199 | IN uint32_t log_level, IN OPTIONAL TeeLogCallback log_callback); 200 | 201 | /*! Initializes a TEE connection 202 | * \param handle A handle to the TEE device. All subsequent calls to the lib's functions 203 | * must be with this handle 204 | * \param guid GUID of the FW client that want to start a session 205 | * \param device optional device path, set NULL to use default 206 | * \return 0 if successful, otherwise error code 207 | */ 208 | TEESTATUS TEEAPI TeeInit(IN OUT PTEEHANDLE handle, IN const GUID *guid, 209 | IN OPTIONAL const char *device); 210 | 211 | #ifdef _WIN32 212 | /*! Initializes a TEE connection 213 | * \param handle A handle to the TEE device. All subsequent calls to the lib's functions 214 | * must be with this handle 215 | * \param guid GUID of the FW client that want to start a session 216 | * \param device optional device class GUID, set NULL to use default 217 | * - use the first device from that class 218 | * \return 0 if successful, otherwise error code 219 | */ 220 | TEESTATUS TEEAPI TeeInitGUID(IN OUT PTEEHANDLE handle, IN const GUID *guid, 221 | IN OPTIONAL const GUID *device); 222 | #endif /* _WIN32 */ 223 | 224 | /*! Initializes a TEE connection 225 | * \param handle A handle to the TEE device. All subsequent calls to the lib's functions 226 | * must be with this handle 227 | * \param guid GUID of the FW client that want to start a session 228 | * \param device_handle open file handle 229 | * \return 0 if successful, otherwise error code 230 | */ 231 | TEESTATUS TEEAPI TeeInitHandle(IN OUT PTEEHANDLE handle, IN const GUID *guid, 232 | IN const TEE_DEVICE_HANDLE device_handle); 233 | 234 | /*! Connects to the TEE driver and starts a session 235 | * \param handle A handle to the TEE device 236 | * \return 0 if successful, otherwise error code 237 | */ 238 | TEESTATUS TEEAPI TeeConnect(OUT PTEEHANDLE handle); 239 | 240 | /*! Read data from the TEE device synchronously. 241 | * \param handle The handle of the session to read from. 242 | * \param buffer A pointer to a buffer that receives the data read from the TEE device. 243 | * \param bufferSize The number of bytes to be read. 244 | * \param pNumOfBytesRead A pointer to the variable that receives the number of bytes read, 245 | * ignored if set to NULL. 246 | * \param timeout The timeout to complete read in milliseconds, zero for infinite 247 | * \return 0 if successful, otherwise error code 248 | */ 249 | TEESTATUS TEEAPI TeeRead(IN PTEEHANDLE handle, IN OUT void *buffer, IN size_t bufferSize, 250 | OUT OPTIONAL size_t *pNumOfBytesRead, IN OPTIONAL uint32_t timeout); 251 | 252 | /*! Writes the specified buffer to the TEE device synchronously. 253 | * \param handle The handle of the session to write to. 254 | * \param buffer A pointer to the buffer containing the data to be written to the TEE device. 255 | * \param bufferSize The number of bytes to be written. 256 | * \param numberOfBytesWritten A pointer to the variable that receives the number of bytes written, 257 | * ignored if set to NULL. 258 | * \param timeout The timeout to complete write in milliseconds, zero for infinite 259 | * \return 0 if successful, otherwise error code 260 | */ 261 | TEESTATUS TEEAPI TeeWrite(IN PTEEHANDLE handle, IN const void *buffer, IN size_t bufferSize, 262 | OUT OPTIONAL size_t *numberOfBytesWritten, IN OPTIONAL uint32_t timeout); 263 | 264 | /*! Retrieves specified FW status register. 265 | * \param handle The handle of the session. 266 | * \param fwStatusNum The FW status register number (0-5). 267 | * \param fwStatus The memory to store obtained FW status. 268 | * \return 0 if successful, otherwise error code. 269 | */ 270 | TEESTATUS TEEAPI TeeFWStatus(IN PTEEHANDLE handle, 271 | IN uint32_t fwStatusNum, OUT uint32_t *fwStatus); 272 | 273 | /*! Retrieves TRC register. 274 | * \param handle The handle of the session. 275 | * \param trc_val The memory to store obtained TRC value. 276 | * \return 0 if successful, otherwise error code. 277 | */ 278 | TEESTATUS TEEAPI TeeGetTRC(IN PTEEHANDLE handle, OUT uint32_t* trc_val); 279 | 280 | /*! Closes the session to TEE driver 281 | * Make sure that you call this function as soon as you are done with the device, 282 | * as other clients might be blocked until the session is closed. 283 | * \param handle The handle of the session to close. 284 | */ 285 | void TEEAPI TeeDisconnect(IN PTEEHANDLE handle); 286 | 287 | /*! Returns handle of TEE device 288 | * Obtains HECI device handle on Windows and mei device file descriptor on Linux 289 | * \param handle The handle of the session. 290 | * \return device handle 291 | */ 292 | TEE_DEVICE_HANDLE TEEAPI TeeGetDeviceHandle(IN PTEEHANDLE handle); 293 | 294 | /*! Structure to store version data 295 | */ 296 | typedef struct { 297 | uint16_t major; /**< Major version number */ 298 | uint16_t minor; /**< Minor version number */ 299 | uint16_t hotfix; /**< Hotfix version number */ 300 | uint16_t build; /**< Build version number */ 301 | } teeDriverVersion_t; 302 | 303 | /*! Obtains version of the TEE device driver 304 | * Not implemented on Linux 305 | * \param handle The handle of the session. 306 | * \param driverVersion Pointer to driver version struct 307 | * \return 0 if successful, otherwise error code. 308 | */ 309 | TEESTATUS TEEAPI GetDriverVersion(IN PTEEHANDLE handle, IN OUT teeDriverVersion_t *driverVersion); 310 | 311 | /*! Set log level 312 | * 313 | * \param handle The handle of the session. 314 | * \param log_level log level to set 315 | * \return previous log level 316 | */ 317 | uint32_t TEEAPI TeeSetLogLevel(IN PTEEHANDLE handle, IN uint32_t log_level); 318 | 319 | /*! Retrieve current log level 320 | * 321 | * \param handle The handle of the session. 322 | * \return current log level 323 | */ 324 | uint32_t TEEAPI TeeGetLogLevel(IN const PTEEHANDLE handle); 325 | 326 | /*! Set log callback 327 | * 328 | * \param handle The handle of the session. 329 | * \param log_callback pointer to function to run for log write, set NULL to use built-in function 330 | * \return 0 if successful, otherwise error code. 331 | */ 332 | TEESTATUS TEEAPI TeeSetLogCallback(IN const PTEEHANDLE handle, TeeLogCallback log_callback); 333 | 334 | /*! Retrieve client maximum message length (MTU) 335 | * 336 | * \param handle The handle of the session. 337 | * \return client maximum message length. 338 | * If client never connected, will return zero. 339 | */ 340 | uint32_t TEEAPI TeeGetMaxMsgLen(IN const PTEEHANDLE handle); 341 | 342 | /*! Retrieve client protocol version 343 | * 344 | * \param handle The handle of the session. 345 | * \return client protocol version. 346 | * If client never connected, will return zero. 347 | */ 348 | uint8_t TEEAPI TeeGetProtocolVer(IN const PTEEHANDLE handle); 349 | 350 | 351 | /*! Obtains kind of the TEE device 352 | * \param handle The handle of the session. 353 | * \param kind Buffer to fill with device kind null terminated string, may be NULL. 354 | * \param kindSize Pointer to kind buffer size in bytes, updated to number of bytes filled in buffer, including null character, on out. 355 | * If buffer is NULL, required size is returned anyway. 356 | * \return 0 if successful, otherwise error code. 357 | */ 358 | TEESTATUS TEEAPI TeeGetKind(IN PTEEHANDLE handle, IN OUT char *kind, IN OUT size_t *kindSize); 359 | 360 | #ifdef __cplusplus 361 | } 362 | #endif 363 | 364 | #endif /* __METEE_H */ 365 | -------------------------------------------------------------------------------- /include/meteepp.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2021-2025 Intel Corporation 4 | */ 5 | /*! \file meteepp.h 6 | \brief metee C++ library API 7 | */ 8 | #ifndef _METEEPP_H_ 9 | #define _METEEPP_H_ 10 | 11 | #include <sstream> 12 | #include <stdexcept> 13 | #include <string> 14 | #include <system_error> 15 | #include <vector> 16 | #include "metee.h" 17 | 18 | namespace intel { 19 | namespace security { 20 | 21 | /*! \def TEE_ERR_STATE(state) 22 | * Internal macro 23 | */ 24 | 25 | /*! MeTee error category class */ 26 | static class metee_category_t : public std::error_category { 27 | public: 28 | virtual const char* name() const noexcept { return "MeTee"; } 29 | virtual std::string message(int ev) const { 30 | #define TEE_ERR_STATE(state) case TEE_##state: return #state 31 | switch (ev) { 32 | TEE_ERR_STATE(SUCCESS); 33 | TEE_ERR_STATE(INTERNAL_ERROR); 34 | TEE_ERR_STATE(DEVICE_NOT_FOUND); 35 | TEE_ERR_STATE(DEVICE_NOT_READY); 36 | TEE_ERR_STATE(INVALID_PARAMETER); 37 | TEE_ERR_STATE(UNABLE_TO_COMPLETE_OPERATION); 38 | TEE_ERR_STATE(TIMEOUT); 39 | TEE_ERR_STATE(NOTSUPPORTED); 40 | TEE_ERR_STATE(CLIENT_NOT_FOUND); 41 | TEE_ERR_STATE(BUSY); 42 | TEE_ERR_STATE(DISCONNECTED); 43 | TEE_ERR_STATE(INSUFFICIENT_BUFFER); 44 | TEE_ERR_STATE(PERMISSION_DENIED); 45 | default: 46 | return std::to_string(ev); 47 | } 48 | #undef TEE_ERR_STATE 49 | } 50 | } metee_category; 51 | 52 | /*! MeTee error exception class class */ 53 | class metee_exception : public std::system_error 54 | { 55 | public: 56 | /*! Constructor 57 | * \param what error string 58 | * \param err error code 59 | */ 60 | metee_exception(const std::string& what, int err = TEE_INTERNAL_ERROR) : std::system_error(err, metee_category, what) {} 61 | /*! Constructor 62 | * \param err error code 63 | * \param cat error category 64 | */ 65 | metee_exception(int err, const std::error_category& cat) : std::system_error(err, cat) {} 66 | /*! Constructor 67 | * \param err error code 68 | * \param cat error category 69 | * \param what error string 70 | */ 71 | metee_exception(int err, const std::error_category& cat, const std::string& what) 72 | : std::system_error(err, cat, what) {} 73 | /*! Destructor */ 74 | virtual ~metee_exception() noexcept {} 75 | }; 76 | 77 | /*! Dummy client GUID for default constructor */ 78 | DEFINE_GUID(METEE_GUID_ZERO, 79 | 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 80 | 81 | /*! Main interface class 82 | * \brief C++ class to access CSE/CSME/GSC firmware via a mei interface. 83 | */ 84 | class metee 85 | { 86 | public: 87 | /*! Default constructor */ 88 | metee() 89 | { 90 | TEESTATUS status = TeeInit(&_handle, &METEE_GUID_ZERO, NULL); 91 | if (!TEE_IS_SUCCESS(status)) { 92 | throw metee_exception("Init failed", status); 93 | } 94 | } 95 | 96 | /*! Constructor 97 | * \param guid GUID of the FW client that want to start a session 98 | * \param log_level log level to set (from enum tee_log_level) 99 | * \param log_callback pointer to function to run for log write, set NULL to use built-in function 100 | */ 101 | metee(const GUID &guid, 102 | uint32_t log_level = TEE_LOG_LEVEL_VERBOSE, TeeLogCallback log_callback = nullptr) 103 | { 104 | struct tee_device_address device = { tee_device_address::TEE_DEVICE_TYPE_NONE , nullptr }; 105 | TEESTATUS status = TeeInitFull(&_handle, &guid, device, log_level, log_callback); 106 | if (!TEE_IS_SUCCESS(status)) { 107 | throw metee_exception("Init failed", status); 108 | } 109 | } 110 | 111 | /*! Constructor 112 | * \param guid GUID of the FW client that want to start a session 113 | * \param device device address structure 114 | * \param log_level log level to set (from enum tee_log_level) 115 | * \param log_callback pointer to function to run for log write, set NULL to use built-in function 116 | */ 117 | metee(const GUID &guid, const struct tee_device_address &device, 118 | uint32_t log_level = TEE_LOG_LEVEL_VERBOSE, TeeLogCallback log_callback = nullptr) 119 | { 120 | TEESTATUS status = TeeInitFull(&_handle, &guid, device, log_level, log_callback); 121 | if (!TEE_IS_SUCCESS(status)) { 122 | throw metee_exception("Init failed", status); 123 | } 124 | } 125 | 126 | /*! Copy constructor - disabled */ 127 | metee(const metee& other) = delete; 128 | 129 | /*! Move constructor 130 | * \param other Object to move from 131 | */ 132 | metee(metee&& other) noexcept : _handle(other._handle) 133 | { 134 | other._handle.handle = nullptr; 135 | } 136 | 137 | /*! Copy operator - disabled */ 138 | metee& operator=(const metee& other) = delete; 139 | 140 | /*! Move operator 141 | * \param other Object to move from 142 | */ 143 | metee& operator=(metee&& other) noexcept 144 | { 145 | TeeDisconnect(&_handle); 146 | _handle = other._handle; 147 | other._handle.handle = nullptr; 148 | return *this; 149 | } 150 | 151 | /*! Destructor, disconnects, if connected */ 152 | virtual ~metee() 153 | { 154 | TeeDisconnect(&_handle); 155 | } 156 | 157 | /*! Connects to the TEE driver and starts a session */ 158 | void connect() 159 | { 160 | TEESTATUS status; 161 | 162 | status = TeeConnect(&_handle); 163 | if (!TEE_IS_SUCCESS(status)) { 164 | throw metee_exception("Connect failed", status); 165 | } 166 | } 167 | 168 | /*! Read data from the TEE device synchronously. 169 | * \param timeout The timeout to complete read in milliseconds, zero for infinite 170 | * \return vector with data read from the TEE device 171 | */ 172 | std::vector<uint8_t> read(uint32_t timeout) 173 | { 174 | TEESTATUS status; 175 | size_t size = 0; 176 | std::vector<uint8_t> buffer(max_msg_len()); 177 | 178 | status = TeeRead(&_handle, buffer.data(), buffer.size(), &size, timeout); 179 | if (!TEE_IS_SUCCESS(status)) { 180 | throw metee_exception("Read failed", status); 181 | } 182 | 183 | buffer.resize(size); 184 | return std::move(buffer); 185 | } 186 | 187 | /*! Writes the specified buffer to the TEE device synchronously. 188 | * \param buffer vector containing the data to be written to the TEE device. 189 | * \param timeout The timeout to complete write in milliseconds, zero for infinite 190 | * \return the number of bytes written 191 | */ 192 | size_t write(const std::vector<uint8_t> &buffer, uint32_t timeout) 193 | { 194 | TEESTATUS status; 195 | size_t size = 0; 196 | 197 | status = TeeWrite(&_handle, buffer.data(), buffer.size(), &size, timeout); 198 | if (!TEE_IS_SUCCESS(status)) { 199 | throw metee_exception("Write failed", status); 200 | } 201 | 202 | return size; 203 | } 204 | 205 | /*! Retrieves specified FW status register. 206 | * \param fwStatusNum The FW status register number (0-5). 207 | * \return obtained FW status. 208 | */ 209 | uint32_t fw_status(uint32_t fwStatusNum) 210 | { 211 | TEESTATUS status; 212 | uint32_t fwStatus = 0; 213 | 214 | status = TeeFWStatus(&_handle, fwStatusNum, &fwStatus); 215 | if (!TEE_IS_SUCCESS(status)) { 216 | throw metee_exception("FWStatus failed", status); 217 | } 218 | 219 | return fwStatus; 220 | } 221 | 222 | /*! Retrieves TRC register. 223 | * \return TRC value. 224 | */ 225 | uint32_t trc() 226 | { 227 | TEESTATUS status; 228 | uint32_t trc_val = 0; 229 | 230 | status = TeeGetTRC(&_handle, &trc_val); 231 | if (!TEE_IS_SUCCESS(status)) { 232 | throw metee_exception("GetTRC failed", status); 233 | } 234 | 235 | return trc_val; 236 | } 237 | 238 | /*! Retrieves device kind. 239 | * \return kind string value. 240 | */ 241 | std::string kind() 242 | { 243 | TEESTATUS status; 244 | const size_t KIND_SIZE = 32; 245 | char kind[KIND_SIZE]; 246 | size_t kind_size = KIND_SIZE; 247 | 248 | status = TeeGetKind(&_handle, kind, &kind_size); 249 | if (!TEE_IS_SUCCESS(status)) { 250 | throw metee_exception("TeeGetKind failed", status); 251 | } 252 | 253 | return kind; 254 | } 255 | /*! Set log level 256 | * 257 | * \param log_level log level to set 258 | * \return previous log level 259 | */ 260 | uint32_t log_level(uint32_t log_level) 261 | { 262 | return TeeSetLogLevel(&_handle, log_level); 263 | } 264 | 265 | /*! Retrieve current log level 266 | * 267 | * \return current log level 268 | */ 269 | uint32_t log_level() 270 | { 271 | return TeeGetLogLevel(&_handle); 272 | } 273 | 274 | /*! Set log callback 275 | * 276 | * \param log_callback pointer to function to run for log write, set NULL to use built-in function 277 | */ 278 | void log_callback(TeeLogCallback log_callback) 279 | { 280 | TeeSetLogCallback(&_handle, log_callback); 281 | } 282 | 283 | /*! Retrieve client maximum message length (MTU) 284 | * 285 | * \return client maximum message length. 286 | */ 287 | uint32_t max_msg_len() 288 | { 289 | return TeeGetMaxMsgLen(&_handle); 290 | } 291 | 292 | /*! Retrieve client protocol version 293 | * 294 | * \return client protocol version. 295 | */ 296 | uint8_t protocol_ver() 297 | { 298 | return TeeGetProtocolVer(&_handle); 299 | } 300 | 301 | /*! Returns handle of TEE device 302 | * Obtains HECI device handle on Windows and mei device file descriptor on Linux 303 | * \return the handle of the session. 304 | */ 305 | TEE_DEVICE_HANDLE device_handle() 306 | { 307 | return TeeGetDeviceHandle(&_handle); 308 | } 309 | 310 | /*! Obtains version of the TEE device driver 311 | * Not implemented on Linux 312 | * \return Driver version as dotted string. 313 | */ 314 | std::string driver_version() 315 | { 316 | TEESTATUS status; 317 | teeDriverVersion_t driverVersion = { 0 }; 318 | 319 | status = ::GetDriverVersion(&_handle, &driverVersion); 320 | if (!TEE_IS_SUCCESS(status)) { 321 | throw metee_exception("GetDriverVersion failed", status); 322 | } 323 | 324 | std::stringstream ss; 325 | ss << driverVersion.major << "." 326 | << driverVersion.minor << "." 327 | << driverVersion.hotfix << "." 328 | << driverVersion.build; 329 | return ss.str(); 330 | } 331 | 332 | private: 333 | _TEEHANDLE _handle; /*!< Internal device handle */ 334 | }; 335 | } // namespace security 336 | } // namespace intel 337 | #endif // _METEEPP_H_ 338 | -------------------------------------------------------------------------------- /linux.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright (C) 2014-2024 Intel Corporation 3 | set(TEE_SOURCES src/linux/metee_linux.c src/linux/mei.c) 4 | 5 | add_library(${PROJECT_NAME} ${TEE_SOURCES}) 6 | 7 | target_include_directories(${PROJECT_NAME} PRIVATE src/linux) 8 | target_compile_definitions(${PROJECT_NAME} PRIVATE 9 | $<$<BOOL:BUILD_SHARED_LIBS>:METEE_DLL> 10 | $<$<BOOL:BUILD_SHARED_LIBS>:METEE_DLL_EXPORT> 11 | ) 12 | 13 | # Check for new IOCTLs 14 | include(CheckSymbolExists) 15 | check_symbol_exists(IOCTL_MEI_CONNECT_CLIENT_VTAG linux/mei.h HAVE_VTAG) 16 | if(NOT HAVE_VTAG) 17 | include_directories(BEFORE "src/linux/include") 18 | endif() 19 | 20 | # More warnings and warning-as-error 21 | set(COMPILE_OPTIONS 22 | -Wall -Werror) 23 | include(CheckCCompilerFlag) 24 | check_c_compiler_flag(-Wshadow WARNING_SHADOW) 25 | if(WARNING_SHADOW) 26 | set(COMPILE_OPTIONS ${COMPILE_OPTIONS} -Wshadow) 27 | endif() 28 | check_c_compiler_flag(-Wnull-dereference WARNING_NULL_DEREFERENCE) 29 | if(WARNING_NULL_DEREFERENCE) 30 | set(COMPILE_OPTIONS ${COMPILE_OPTIONS} -Wnull-dereference) 31 | endif() 32 | check_c_compiler_flag(-Wfloat-conversion WARNING_FLOAT_CONVERSION) 33 | if(WARNING_FLOAT_CONVERSION) 34 | set(COMPILE_OPTIONS ${COMPILE_OPTIONS} -Wfloat-conversion) 35 | endif() 36 | check_c_compiler_flag(-Wsign-conversion WARNING_SIGN_CONVERSION) 37 | if(WARNING_SIGN_CONVERSION) 38 | set(COMPILE_OPTIONS ${COMPILE_OPTIONS} -Wsign-conversion) 39 | endif() 40 | check_c_compiler_flag(-Wstringop-truncation WARNING_STRINGOP_TRUNCATION) 41 | if(WARNING_STRINGOP_TRUNCATION) 42 | set(COMPILE_OPTIONS ${COMPILE_OPTIONS} -Wstringop-truncation) 43 | endif() 44 | check_c_compiler_flag(-Wjump-misses-init WARNING_JUMP_MISSES_INIT) 45 | if(WARNING_JUMP_MISSES_INIT) 46 | set(COMPILE_OPTIONS ${COMPILE_OPTIONS} -Wjump-misses-init) 47 | endif() 48 | check_c_compiler_flag(-Wunsuffixed-float-constants WARNING_UNSUFFIXED_FLOAT_CONSTANTS) 49 | if(WARNING_UNSUFFIXED_FLOAT_CONSTANTS) 50 | set(COMPILE_OPTIONS ${COMPILE_OPTIONS} -Wunsuffixed-float-constants) 51 | endif() 52 | target_compile_options( 53 | ${PROJECT_NAME} 54 | PRIVATE ${COMPILE_OPTIONS}) 55 | # Security options 56 | target_compile_options( 57 | ${PROJECT_NAME} 58 | PRIVATE -fstack-protector-strong -D_FORTIFY_SOURCE=2 -O2 -Wformat 59 | -Wformat-security 60 | PRIVATE $<$<C_COMPILER_ID:GNU>:-fno-strict-overflow> 61 | PRIVATE $<$<C_COMPILER_ID:GNU>:-fno-delete-null-pointer-checks> 62 | PRIVATE -fwrapv 63 | ) 64 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z noexecstack -z relro -z now") 65 | set_target_properties(${PROJECT_NAME} PROPERTIES C_VISIBILITY_PRESET hidden) 66 | 67 | if(NOT CONSOLE_OUTPUT) 68 | target_compile_definitions(${PROJECT_NAME} PRIVATE -DSYSLOG) 69 | endif() 70 | 71 | target_compile_definitions(${PROJECT_NAME} PRIVATE -D_GNU_SOURCE) 72 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright (C) 2020-2022 Intel Corporation 3 | project('metee', 'c', 4 | version : run_command('get-version.py').stdout().strip(), 5 | license : 'Apache 2.0', 6 | meson_version : '>=0.51.0', 7 | default_options : ['warning_level=2', 8 | 'default_library=static', 9 | 'c_std=gnu99', 10 | 'optimization=2'], 11 | ) 12 | 13 | metee_sources_linux = [ 14 | 'src/linux/metee_linux.c', 15 | 'src/linux/mei.c' 16 | ] 17 | 18 | metee_sources_windows = [ 19 | 'src/Windows/metee_win.c', 20 | 'src/Windows/metee_winhelpers.c' 21 | ] 22 | 23 | warning_flags = [ 24 | '-Wno-unused-command-line-argument', 25 | '-Wsign-compare', 26 | '-Wformat-security', 27 | '-Wstack-protector', 28 | '-Winit-self', 29 | '/WX', 30 | '/W4' 31 | ] 32 | 33 | # secure compile flags 34 | security_flags = [ 35 | '-fstack-protector-strong', 36 | '-Wformat', 37 | '-Wformat-security', 38 | '-fno-strict-overflow', 39 | '-fno-delete-null-pointer-checks', 40 | '-fwrapv', 41 | '/GS', 42 | '/sdl' 43 | ] 44 | 45 | if get_option('optimization').to_int() >= 2 46 | security_flags += [ 47 | '-D_FORTIFY_SOURCE=2' 48 | ] 49 | endif 50 | 51 | debug_flags = [] 52 | if get_option('buildtype') == 'debug' 53 | debug_flags += [ 54 | '-O0', 55 | '-g3', 56 | '-ggdb' 57 | ] 58 | endif 59 | 60 | cc = meson.get_compiler('c') 61 | if cc.get_id() == 'msvc' 62 | add_project_arguments('-DUNICODE', '-D_UNICODE', 63 | language : 'c') 64 | if get_option('mvsc_runtime_static') 65 | if get_option('buildtype') == 'debug' 66 | add_project_arguments('/MT', language : 'c') 67 | else 68 | add_project_arguments('/MTd', language : 'c') 69 | endif 70 | endif 71 | endif 72 | 73 | add_project_arguments(cc.get_supported_arguments(warning_flags), 74 | language : 'c') 75 | add_project_arguments(cc.get_supported_arguments(security_flags), 76 | language : 'c') 77 | add_project_arguments(cc.get_supported_arguments(debug_flags), 78 | language : 'c') 79 | add_project_arguments('-D_XOPEN_SOURCE=700', language : 'c') 80 | 81 | global_link_args = [] 82 | test_link_args = [ 83 | '-Wl,-z,relro', 84 | '-Wl,-z,now', 85 | '-Wl,-z,noexecstack', 86 | ] 87 | foreach link_arg: test_link_args 88 | if cc.has_link_argument(link_arg) 89 | global_link_args += link_arg 90 | endif 91 | endforeach 92 | add_project_link_arguments( 93 | global_link_args, 94 | language: 'c' 95 | ) 96 | 97 | if target_machine.system() == 'linux' 98 | local_inc = ['include', 'src/linux'] 99 | if not cc.has_header_symbol('linux/mei.h', 'IOCTL_MEI_CONNECT_CLIENT_VTAG') 100 | local_inc = ['src/linux/include'] + local_inc 101 | endif 102 | metee_lib_static = static_library('metee', 103 | sources : metee_sources_linux, 104 | include_directories : local_inc 105 | ) 106 | elif target_machine.system() == 'windows' 107 | metee_lib_static = static_library('metee', 108 | sources : metee_sources_windows, 109 | include_directories : ['include', 'src/Windows'], 110 | link_args : ['CfgMgr32.lib'] 111 | ) 112 | endif 113 | 114 | metee_dep_static = declare_dependency( 115 | link_with : metee_lib_static, 116 | include_directories : include_directories('include'), 117 | ) 118 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright (C) 2020 Intel Corporation 3 | 4 | option('mvsc_runtime_static', 5 | type : 'boolean', 6 | value : 'true', 7 | description : 'Build with static runtime libraries on MSVC' 8 | ) 9 | -------------------------------------------------------------------------------- /samples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright (C) 2014-2024 Intel Corporation 3 | cmake_minimum_required(VERSION 3.15) 4 | project(metee_sample) 5 | 6 | add_executable(metee-mkhi metee_mkhi.c) 7 | target_link_libraries(metee-mkhi metee) 8 | if(MSVC) 9 | target_compile_definitions(metee-mkhi PRIVATE -D_CRT_SECURE_NO_WARNINGS) 10 | endif() 11 | install(TARGETS metee-mkhi RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 12 | 13 | add_executable(metee-gsc metee_gsc.c) 14 | target_link_libraries(metee-gsc metee) 15 | install(TARGETS metee-gsc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 16 | 17 | if(UNIX) 18 | add_executable(metee-connect metee_connect.c meiuuid.c) 19 | 20 | target_link_libraries(metee-connect metee) 21 | 22 | install(TARGETS metee-connect RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 23 | endif(UNIX) 24 | 25 | add_executable(metee-trc metee_trc.c) 26 | target_link_libraries(metee-trc metee) 27 | install(TARGETS metee-trc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 28 | 29 | add_executable(metee-basic metee_basic.c) 30 | target_link_libraries(metee-basic metee) 31 | install(TARGETS metee-basic RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) -------------------------------------------------------------------------------- /samples/meiuuid.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2014-2024 Intel Corporation 4 | */ 5 | #include <stdlib.h> 6 | #include <stdint.h> 7 | #include <ctype.h> 8 | #include <string.h> 9 | 10 | #include "metee.h" 11 | #include "meiuuid.h" 12 | 13 | int mei_uuid_parse(const char *str, GUID *uuid) 14 | { 15 | const char *p = "00000000-0000-0000-0000-000000000000"; 16 | const size_t len = strlen(p); 17 | uint32_t a; 18 | uint16_t b, c; 19 | uint8_t d[2], e[6]; 20 | char buf[3]; 21 | int i; 22 | 23 | if (strlen(str) != len) 24 | return -1; 25 | 26 | for (i = 0; i < len; i++) { 27 | if (str[i] == '-') { 28 | if (p[i] == '-') 29 | continue; 30 | else 31 | return -1; 32 | } else if (!isxdigit(str[i])) { 33 | return -1; 34 | } 35 | } 36 | 37 | a = strtoul(str + 0, NULL, 16); 38 | b = strtoul(str + 9, NULL, 16); 39 | c = strtoul(str + 14, NULL, 16); 40 | 41 | buf[2] = 0; 42 | for (i = 0; i < 2; i++) { 43 | buf[0] = str[19 + i * 2]; 44 | buf[1] = str[19 + i * 2 + 1]; 45 | d[i] = strtoul(buf, NULL, 16); 46 | } 47 | 48 | for (i = 0; i < 6; i++) { 49 | buf[0] = str[24 + i * 2]; 50 | buf[1] = str[24 + i * 2 + 1]; 51 | e[i] = strtoul(buf, NULL, 16); 52 | } 53 | 54 | uuid->l = a; 55 | uuid->w1 = b; 56 | uuid->w2 = c; 57 | uuid->b[0] = d[0]; 58 | uuid->b[1] = d[1]; 59 | uuid->b[2] = e[0]; 60 | uuid->b[3] = e[1]; 61 | uuid->b[4] = e[2]; 62 | uuid->b[5] = e[3]; 63 | uuid->b[6] = e[4]; 64 | uuid->b[7] = e[5]; 65 | 66 | return 0; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /samples/meiuuid.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2014-2024 Intel Corporation 4 | */ 5 | int mei_uuid_parse(const char *str, GUID *uuid); 6 | -------------------------------------------------------------------------------- /samples/metee_basic.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2024-2025 Intel Corporation 4 | */ 5 | #include <stdio.h> 6 | #include <stdlib.h> 7 | #ifdef __linux__ 8 | #include <unistd.h> 9 | #endif /* __linux__ */ 10 | 11 | #include <metee.h> 12 | 13 | DEFINE_GUID(MEI_MKHIF, 0x8e6a6715, 0x9abc, 0x4043, 14 | 0x88, 0xef, 0x9e, 0x39, 0xc6, 0xf6, 0x3e, 0xf); 15 | 16 | #define MKHI_TIMEOUT 10000 17 | #define CONNECT_RETRIES 3 18 | 19 | #pragma pack(1) 20 | struct mkhi_msg_hdr { 21 | union { 22 | uint32_t data; 23 | struct { 24 | uint32_t GroupId : 8; 25 | uint32_t Command : 7; 26 | uint32_t IsResponse : 1; 27 | uint32_t Reserved : 8; 28 | uint32_t Result : 8; 29 | }; 30 | }; 31 | }; 32 | 33 | struct mkhi_fwver_req { 34 | struct mkhi_msg_hdr header; 35 | }; 36 | 37 | struct mkhi_fw_version_block { 38 | uint16_t minor; 39 | uint16_t major; 40 | uint16_t buildNo; 41 | uint16_t hotFix; 42 | }; 43 | 44 | struct mkhi_fw_version { 45 | struct mkhi_fw_version_block code; 46 | struct mkhi_fw_version_block NFTP; 47 | struct mkhi_fw_version_block FITC; 48 | }; 49 | 50 | struct mkhi_fwver_rsp { 51 | struct mkhi_msg_hdr header; 52 | struct mkhi_fw_version version; 53 | }; 54 | #pragma pack() 55 | 56 | int main(int argc, char* argv[]) 57 | { 58 | TEEHANDLE handle; 59 | TEESTATUS status; 60 | struct tee_device_address addr = { 61 | .type = TEE_DEVICE_TYPE_NONE, 62 | .data.path = NULL 63 | }; 64 | int retry = CONNECT_RETRIES; 65 | size_t written = 0; 66 | struct mkhi_fwver_req req; 67 | uint8_t *read_buf = NULL; 68 | struct mkhi_fwver_rsp* rsp; 69 | char kind[32]; 70 | size_t kind_size = sizeof(kind); 71 | 72 | status = TeeInitFull(&handle, &MEI_MKHIF, addr, TEE_LOG_LEVEL_VERBOSE, NULL); 73 | if (!TEE_IS_SUCCESS(status)) { 74 | fprintf(stderr, "TeeInitFull failed with status = %u\n", status); 75 | return 1; 76 | } 77 | 78 | status = TeeGetKind(&handle, kind, &kind_size); 79 | if (!TEE_IS_SUCCESS(status)) { 80 | fprintf(stderr, "TeeGetKind failed with status = %u\n", status); 81 | } else { 82 | printf("Tee device kind is %s\n", kind); 83 | } 84 | 85 | while (retry--) { 86 | status = TeeConnect(&handle); 87 | if (status != TEE_BUSY && 88 | status != TEE_UNABLE_TO_COMPLETE_OPERATION) /* windows return this error on busy */ 89 | break; 90 | fprintf(stderr, "Client is busy, retrying\n"); 91 | #ifdef WIN32 92 | Sleep(2000); 93 | #else 94 | sleep(2); 95 | #endif /* WIN32 */ 96 | } 97 | switch (status) { 98 | case TEE_SUCCESS: 99 | break; 100 | case TEE_CLIENT_NOT_FOUND: 101 | fprintf(stderr, "TeeConnect failed with status = %u (Client not found)\n", status); 102 | goto out; 103 | default: 104 | fprintf(stderr, "TeeConnect failed with status = %u\n", status); 105 | goto out; 106 | } 107 | 108 | if (TeeGetMaxMsgLen(&handle) == 0) 109 | { 110 | fprintf(stderr, "Client reported zero MTU. Aborting.\n"); 111 | goto out; 112 | } 113 | 114 | /* Write */ 115 | req.header.data = 0; /* Reset */ 116 | req.header.GroupId = 0xFF; /* MKHI */ 117 | req.header.Command = 0x02; /* GET FW Version */ 118 | req.header.IsResponse = 0; 119 | req.header.Reserved = 0; 120 | 121 | status = TeeWrite(&handle, &req, sizeof(req), &written, MKHI_TIMEOUT); 122 | if (!TEE_IS_SUCCESS(status)) { 123 | fprintf(stderr, "TeeWrite failed with status = %u\n", status); 124 | goto out; 125 | } 126 | if (written != sizeof(req)) { 127 | fprintf(stderr, "TeeWrite failed written = %zu\n", written); 128 | status = TEE_INTERNAL_ERROR; 129 | goto out; 130 | } 131 | 132 | /* Read */ 133 | read_buf = (uint8_t*)malloc(TeeGetMaxMsgLen(&handle)); 134 | if (!read_buf) { 135 | fprintf(stderr, "malloc failed\n"); 136 | status = TEE_INTERNAL_ERROR; 137 | goto out; 138 | } 139 | 140 | status = TeeRead(&handle, read_buf, TeeGetMaxMsgLen(&handle), &written, MKHI_TIMEOUT); 141 | if (!TEE_IS_SUCCESS(status)) { 142 | fprintf(stderr, "TeeWrite failed with status = %u\n", status); 143 | goto out; 144 | } 145 | 146 | rsp = (struct mkhi_fwver_rsp*)read_buf; 147 | 148 | if (written < sizeof(struct mkhi_msg_hdr)) { 149 | fprintf(stderr, "Returned less then header = %zu\n", written); 150 | status = TEE_INTERNAL_ERROR; 151 | goto out; 152 | } 153 | 154 | if (written < sizeof(struct mkhi_fwver_rsp)) { 155 | fprintf(stderr, "Returned less then response = %zu\n", written); 156 | status = TEE_INTERNAL_ERROR; 157 | goto out; 158 | } 159 | 160 | if (rsp->header.Result) { 161 | fprintf(stderr, "Result = %u\n", rsp->header.Result); 162 | status = TEE_INTERNAL_ERROR; 163 | goto out; 164 | } 165 | 166 | printf("Version: %u.%u.%u.%u\n", 167 | rsp->version.code.major, rsp->version.code.minor, rsp->version.code.hotFix, rsp->version.code.buildNo); 168 | 169 | out: 170 | TeeDisconnect(&handle); 171 | if (read_buf) 172 | free(read_buf); 173 | return TEE_IS_SUCCESS(status) ? 0 : 1; 174 | } 175 | -------------------------------------------------------------------------------- /samples/metee_connect.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2014-2024 Intel Corporation 4 | */ 5 | #include <stdio.h> 6 | #include <stdlib.h> 7 | #include <string.h> 8 | #include <fcntl.h> 9 | #include <sys/ioctl.h> 10 | #include <unistd.h> 11 | #include <errno.h> 12 | #include <stdint.h> 13 | #include <stdbool.h> 14 | #include <limits.h> 15 | #include <ctype.h> 16 | #include <linux/mei.h> 17 | #include <metee.h> 18 | #include "meiuuid.h" 19 | 20 | struct params { 21 | bool verbose; 22 | GUID uuid; 23 | int iterations; 24 | }; 25 | 26 | static int work(struct params *p) 27 | { 28 | TEEHANDLE cl; 29 | const unsigned char cmd[] = "AB"; 30 | const ssize_t sz = sizeof(cmd); 31 | unsigned char *buf = NULL; 32 | size_t rsz, wsz; 33 | int i; 34 | TEESTATUS status; 35 | 36 | status = TeeInit(&cl, &p->uuid, NULL); 37 | if (status != TEE_SUCCESS) 38 | goto out; 39 | 40 | status = TeeConnect(&cl); 41 | if (status != TEE_SUCCESS) 42 | goto out; 43 | 44 | rsz = TeeGetMaxMsgLen(&cl); 45 | if (rsz == 0) 46 | { 47 | fprintf(stderr, "client reproted zero MTU.\n"); 48 | goto out; 49 | } 50 | buf = (unsigned char *)malloc(rsz); 51 | if (buf == NULL) 52 | goto out; 53 | memset(buf, 0, rsz); 54 | 55 | for (i = 0; i < p->iterations; i++) { 56 | 57 | status = TeeWrite(&cl, cmd , sz, &wsz, 0); 58 | if (status != TEE_SUCCESS) 59 | goto out; 60 | 61 | if (wsz != sz) { 62 | status = TEE_UNABLE_TO_COMPLETE_OPERATION; 63 | goto out; 64 | } 65 | 66 | status = TeeRead(&cl, buf, rsz, NULL, 10000); 67 | if (status != TEE_SUCCESS) 68 | goto out; 69 | } 70 | out: 71 | TeeDisconnect(&cl); 72 | free(buf); 73 | return status; 74 | } 75 | 76 | 77 | 78 | static void usage(const char *p) 79 | { 80 | fprintf(stdout, "%s: -u <uuid> [-i <iterations>] [-h]\n", p); 81 | } 82 | 83 | #define BIT(_x) (1L<<(_x)) 84 | #define UUID_BIT BIT(1) 85 | #define ITER_BIT BIT(2) 86 | 87 | static int mei_getopt(int argc, char *argv[], struct params *p) 88 | { 89 | 90 | unsigned long required = UUID_BIT; 91 | unsigned long present = 0; 92 | 93 | extern char *optarg; 94 | int opt; 95 | 96 | while ((opt = getopt(argc, argv, "hvu:i:")) != -1) { 97 | switch (opt) { 98 | case 'v': 99 | p->verbose = true; 100 | break; 101 | case 'u': 102 | present |= UUID_BIT; 103 | if (mei_uuid_parse(optarg, &p->uuid) < 0) 104 | return -1; 105 | break; 106 | case 'i': 107 | present |= ITER_BIT; 108 | p->iterations = strtoul(optarg, NULL, 10); 109 | break; 110 | case 'h': 111 | case '?': 112 | usage(argv[0]); 113 | break; 114 | } 115 | } 116 | 117 | if ((required & present) != required) { 118 | usage(argv[0]); 119 | return -1; 120 | } 121 | return 0; 122 | } 123 | 124 | int main(int argc, char *argv[]) 125 | { 126 | struct params p; 127 | int rc; 128 | 129 | p.verbose = false; 130 | memset(&p.uuid, 0, sizeof(p.uuid)); 131 | p.iterations = 1; 132 | 133 | #ifdef _WIN32 134 | //p.uuid = ; 135 | #else 136 | rc = mei_getopt(argc, argv, &p); 137 | if (rc) { 138 | usage(argv[0]); 139 | exit(EXIT_FAILURE); 140 | } 141 | #endif /* _WIN32 */ 142 | 143 | rc = work(&p); 144 | exit(rc); 145 | } 146 | -------------------------------------------------------------------------------- /samples/metee_gsc.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2020-2024 Intel Corporation 4 | */ 5 | #include <stdio.h> 6 | #include <stdlib.h> 7 | #include <string.h> 8 | #include <fcntl.h> 9 | #include <errno.h> 10 | #include <stdint.h> 11 | #include <metee.h> 12 | 13 | #ifndef BIT 14 | #define BIT(n) 1 << (n) 15 | #endif /* BIT */ 16 | 17 | #include <stdbool.h> 18 | #ifdef _WIN32 19 | typedef SSIZE_T ssize_t; 20 | #else 21 | #include <unistd.h> 22 | #endif /* _WIN32 */ 23 | 24 | #pragma pack(1) 25 | struct gsc_fwu_heci_header { 26 | uint8_t command_id; 27 | uint8_t is_response :1; 28 | uint8_t reserved :7; 29 | uint8_t reserved2[2]; 30 | }; 31 | 32 | struct gsc_fwu_heci_version_req { 33 | struct gsc_fwu_heci_header header; 34 | uint32_t partition; 35 | }; 36 | 37 | struct gsc_fwu_heci_response { 38 | struct gsc_fwu_heci_header header; 39 | uint32_t status; 40 | uint32_t reserved; 41 | }; 42 | 43 | struct gsc_fwu_heci_version_resp { 44 | struct gsc_fwu_heci_response response; 45 | uint32_t partition; 46 | uint32_t version_length; 47 | uint8_t version[]; 48 | }; 49 | 50 | struct gsc_fwu_external_version { 51 | char project[4]; 52 | uint16_t hotfix; 53 | uint16_t build; 54 | }; 55 | #pragma pack() 56 | 57 | #define GSC_FWU_HECI_COMMAND_ID_GET_IP_VERSION 6 58 | 59 | enum gsc_fwu_heci_payload_type { 60 | gsc_fwu_heci_payload_type_invalid = 0, /**< lower sentinel */ 61 | gsc_fwu_heci_payload_type_gfx_fw = 1, /**< graphics firmware */ 62 | gsc_fwu_heci_payload_type_oprom_data = 2, /**< oprom data partition */ 63 | gsc_fwu_heci_payload_type_oprom_code = 3, /**< oprom code partition */ 64 | }; 65 | 66 | /** GSC firmware update status SUCCESS */ 67 | #define GSC_FWU_STATUS_SUCCESS 0x0 68 | /** GSC firmware update status size error */ 69 | #define GSC_FWU_STATUS_SIZE_ERROR 0x5 70 | /** GSC Update oprom section does not exists error */ 71 | #define GSC_FWU_STATUS_INVALID_COMMAND 0x8D 72 | /** GSC firmware update status invalid param error */ 73 | #define GSC_FWU_STATUS_INVALID_PARAMS 0x85 74 | /** GSC firmware update general failure */ 75 | #define GSC_FWU_STATUS_FAILURE 0x9E 76 | 77 | #define MKHI_READ_TIMEOUT 10000 78 | 79 | const char *mkhi_status(uint32_t status) 80 | { 81 | #define MKH_STATUS(_x) case _x: return #_x 82 | switch(status) { 83 | MKH_STATUS(GSC_FWU_STATUS_SUCCESS); 84 | MKH_STATUS(GSC_FWU_STATUS_SIZE_ERROR); 85 | MKH_STATUS(GSC_FWU_STATUS_INVALID_COMMAND); 86 | MKH_STATUS(GSC_FWU_STATUS_INVALID_PARAMS); 87 | MKH_STATUS(GSC_FWU_STATUS_FAILURE); 88 | default: 89 | fprintf(stderr, "unknown 0x%08X\n", status); 90 | return "unknown"; 91 | } 92 | #undef MKH_STATUS 93 | } 94 | 95 | DEFINE_GUID(GUID_DEVINTERFACE_HECI_GSC_CHILD, 96 | 0x5315db55, 0xe7c7, 0x4e67, 97 | 0xb3, 0x96, 0x80, 0xa, 0x75, 0xdd, 0x6f, 0xe4); 98 | DEFINE_GUID(GUID_METEE_FWU, 0x87d90ca5, 0x3495, 0x4559, 99 | 0x81, 0x05, 0x3f, 0xbf, 0xa3, 0x7b, 0x8b, 0x79); 100 | 101 | 102 | struct mk_host_if { 103 | TEEHANDLE mei_cl; 104 | bool initialized; 105 | bool reconnect; 106 | bool verbose; 107 | }; 108 | 109 | static bool mk_host_if_connect(struct mk_host_if *acmd) 110 | { 111 | acmd->initialized = (TeeConnect(&acmd->mei_cl) == 0); 112 | return acmd->initialized; 113 | } 114 | 115 | static bool mk_host_if_init(struct mk_host_if *acmd, const GUID *guid, 116 | bool reconnect, bool verbose) 117 | { 118 | acmd->reconnect = reconnect; 119 | acmd->verbose = verbose; 120 | #ifdef WIN32 121 | TeeInitGUID(&acmd->mei_cl, guid, &GUID_DEVINTERFACE_HECI_GSC_CHILD); 122 | #else 123 | TeeInit(&acmd->mei_cl, guid, NULL); 124 | #endif /* WIN32 */ 125 | return mk_host_if_connect(acmd); 126 | } 127 | 128 | static void mk_host_if_deinit(struct mk_host_if *acmd) 129 | { 130 | TeeDisconnect(&acmd->mei_cl); 131 | } 132 | 133 | static uint32_t mkhi_verify_response_header(struct gsc_fwu_heci_header *msg, struct gsc_fwu_heci_header *resp) 134 | { 135 | bool match = true; 136 | if (msg->command_id != resp->command_id) { 137 | printf("Mismatch Command; Req-Command = %d , Resp-Command = %d\n", 138 | msg->command_id, resp->command_id); 139 | match = false; 140 | } 141 | if (resp->is_response != 1) { 142 | printf("Wrong IsResponse; Resp-IsResponse = %d\n", resp->is_response); 143 | match = false; 144 | } 145 | 146 | return match ? GSC_FWU_STATUS_SUCCESS : GSC_FWU_STATUS_FAILURE; 147 | } 148 | 149 | static uint32_t mk_host_if_call(struct mk_host_if *acmd, 150 | const unsigned char *command, ssize_t command_sz, 151 | uint8_t **read_buf, uint32_t rcmd, 152 | unsigned int expected_sz) 153 | { 154 | uint32_t in_buf_sz; 155 | size_t out_buf_sz; 156 | size_t written; 157 | TEESTATUS status; 158 | struct gsc_fwu_heci_response *msg_hdr; 159 | int count = 0; 160 | 161 | in_buf_sz = TeeGetMaxMsgLen(&acmd->mei_cl); 162 | if (in_buf_sz == 0) 163 | { 164 | if (acmd->verbose) 165 | fprintf(stderr, "mkhif: client reproted zero MTU.\n"); 166 | return GSC_FWU_STATUS_FAILURE; 167 | } 168 | *read_buf = (uint8_t *)malloc(in_buf_sz); 169 | if (*read_buf == NULL) 170 | return GSC_FWU_STATUS_FAILURE; 171 | memset(*read_buf, 0, in_buf_sz); 172 | msg_hdr = (struct gsc_fwu_heci_response *)*read_buf; 173 | 174 | while (count++ < 2) { 175 | status = TeeWrite(&acmd->mei_cl, command, command_sz, &written, 0); 176 | if (status || written != command_sz) { 177 | if(!acmd->reconnect || !mk_host_if_connect(acmd)) 178 | return GSC_FWU_STATUS_FAILURE; 179 | continue; 180 | } 181 | break; 182 | } 183 | 184 | status = TeeRead(&acmd->mei_cl, *read_buf, in_buf_sz, &out_buf_sz, MKHI_READ_TIMEOUT); 185 | if (status) 186 | return GSC_FWU_STATUS_FAILURE; 187 | 188 | status = msg_hdr->status; 189 | if (acmd->verbose) 190 | fprintf(stderr, "mkhif: message header read status = %d\n", status); 191 | 192 | status = mkhi_verify_response_header((struct gsc_fwu_heci_header *)command, &msg_hdr->header); 193 | if (status != GSC_FWU_STATUS_SUCCESS) 194 | return status; 195 | 196 | if (expected_sz && expected_sz != out_buf_sz) { 197 | return GSC_FWU_STATUS_FAILURE; 198 | } 199 | return GSC_FWU_STATUS_SUCCESS; 200 | } 201 | 202 | static void printf_if_fw_version(struct gsc_fwu_external_version *version) 203 | { 204 | printf("Firmware Version %c%c%c%c.%d.%d\n", 205 | version->project[0], version->project[1], 206 | version->project[2], version->project[3], 207 | version->hotfix, version->build); 208 | } 209 | 210 | 211 | static uint32_t mk_host_if_fw_version(struct mk_host_if *cmd, 212 | struct gsc_fwu_external_version *version) 213 | { 214 | struct gsc_fwu_heci_version_req req; 215 | struct gsc_fwu_heci_version_resp *response = NULL; 216 | uint32_t status; 217 | size_t size = sizeof(struct gsc_fwu_heci_version_resp) + sizeof(struct gsc_fwu_external_version); 218 | 219 | req.header.command_id = GSC_FWU_HECI_COMMAND_ID_GET_IP_VERSION; /* GET FW Version */ 220 | req.header.is_response = 0; 221 | req.header.reserved = 0; 222 | req.header.reserved2[0] = 0; 223 | req.header.reserved2[1] = 0; 224 | req.partition = gsc_fwu_heci_payload_type_gfx_fw; 225 | 226 | status = mk_host_if_call(cmd, 227 | (const unsigned char *)&req, sizeof(req), 228 | (uint8_t **)&response, 229 | 0, (unsigned int)size); 230 | 231 | if (status != GSC_FWU_STATUS_SUCCESS) { 232 | return status; 233 | } 234 | memcpy(version, response->version, sizeof(struct gsc_fwu_external_version)); 235 | 236 | return status; 237 | } 238 | 239 | static uint32_t mk_host_if_fw_version_req(struct mk_host_if *acmd) 240 | { 241 | struct gsc_fwu_heci_version_req req; 242 | unsigned char *buf = (unsigned char *)&req; 243 | size_t written; 244 | TEESTATUS status; 245 | 246 | req.header.command_id = GSC_FWU_HECI_COMMAND_ID_GET_IP_VERSION; /* GET FW Version */ 247 | req.header.is_response = 0; 248 | req.header.reserved = 0; 249 | req.header.reserved2[0] = 0; 250 | req.header.reserved2[1] = 0; 251 | req.partition = gsc_fwu_heci_payload_type_gfx_fw; 252 | 253 | status = TeeWrite(&acmd->mei_cl, buf, sizeof(req), &written, 0); 254 | if (status || written != sizeof(req)) 255 | return GSC_FWU_STATUS_FAILURE; 256 | 257 | return GSC_FWU_STATUS_SUCCESS; 258 | } 259 | 260 | static uint32_t mk_host_if_fw_version_resp(struct mk_host_if *acmd) 261 | { 262 | size_t recvd; 263 | TEESTATUS status; 264 | unsigned char rec_msg[100]; 265 | struct gsc_fwu_heci_version_resp *response = (struct gsc_fwu_heci_version_resp *)rec_msg; 266 | size_t size = sizeof(struct gsc_fwu_heci_version_resp) + sizeof(struct gsc_fwu_external_version); 267 | 268 | status = TeeRead(&acmd->mei_cl, rec_msg, size, &recvd, MKHI_READ_TIMEOUT); 269 | if (status || recvd <= 0) 270 | return GSC_FWU_STATUS_FAILURE; 271 | printf_if_fw_version((struct gsc_fwu_external_version *)response->version); 272 | return GSC_FWU_STATUS_SUCCESS; 273 | } 274 | 275 | static void usage(const char *p) 276 | { 277 | fprintf(stderr, "Usage: %s [-hv] [-e <l> ] [-i <n> ] [-b M.m.f.b] [-r] [-s <seq>] [-k <n>]\n", p); 278 | fprintf(stderr, " -h help\n"); 279 | fprintf(stderr, " -v verbose\n"); 280 | fprintf(stderr, " -i <n> iterate n times\n"); 281 | fprintf(stderr, " -r reconnect if failed to write\n"); 282 | fprintf(stderr, " -k <n> timeout between iterations in microseconds (default: 0)\n"); 283 | } 284 | 285 | int main(int argc, char *argv[]) 286 | { 287 | 288 | struct mk_host_if acmd; 289 | 290 | /* Version Data */ 291 | struct gsc_fwu_external_version version; 292 | 293 | unsigned int i, iterations = 1; 294 | const GUID *guid = &GUID_METEE_FWU; 295 | char *sequence = NULL; 296 | 297 | bool verbose = false; 298 | int ret = 0; 299 | bool reconnect = false; 300 | unsigned long iter_timeout = 0; 301 | 302 | #ifdef _WIN32 303 | verbose = true; 304 | reconnect = true; 305 | #else 306 | size_t echo_size; 307 | extern char *optarg; 308 | int opt; 309 | 310 | while ((opt = getopt(argc, argv, "hv:i:s:rk:")) != -1) { 311 | switch (opt) { 312 | case 'v': 313 | verbose = true; 314 | break; 315 | case 'i': 316 | ret = sscanf(optarg,"%u", &iterations); 317 | if (ret != 1) { 318 | usage(argv[0]); 319 | exit(1); 320 | } 321 | break; 322 | case 's': 323 | sequence = optarg; 324 | break; 325 | case 'r': 326 | reconnect = true; 327 | break; 328 | case 'k': 329 | ret = sscanf(optarg,"%lu", &iter_timeout); 330 | if (ret != 1) { 331 | usage(argv[0]); 332 | exit(1); 333 | } 334 | break; 335 | case 'h': 336 | usage(argv[0]); 337 | exit(EXIT_SUCCESS); 338 | case '?': 339 | default: 340 | usage(argv[0]); 341 | exit(EXIT_FAILURE); 342 | } 343 | } 344 | #endif /* _WIN32 */ 345 | 346 | 347 | if (!mk_host_if_init(&acmd, guid, reconnect, verbose)) { 348 | ret = 1; 349 | goto out; 350 | } 351 | 352 | if (sequence) { 353 | for (i = 0; i < strlen(sequence); i++) { 354 | if (sequence[i] == 's') 355 | mk_host_if_fw_version_req(&acmd); 356 | else if (sequence[i] == 'r') 357 | mk_host_if_fw_version_resp(&acmd); 358 | } 359 | } 360 | 361 | for (i = 0; i < iterations ; i++) { 362 | if (iter_timeout && i > 0) { 363 | printf("Sleeping for %lu microseconds ...\n", iter_timeout); 364 | #ifdef _WIN32 365 | Sleep(iter_timeout/1000); 366 | #else 367 | usleep(iter_timeout); 368 | #endif /* _WIN32_ */ 369 | } 370 | printf("Running version test %d...\n", i); 371 | memset(&version, 0, sizeof(version)); 372 | ret = mk_host_if_fw_version(&acmd, &version); 373 | if (ret != GSC_FWU_STATUS_SUCCESS) 374 | goto out; 375 | 376 | printf_if_fw_version(&version); 377 | 378 | if (ret != GSC_FWU_STATUS_SUCCESS) 379 | goto out; 380 | } 381 | 382 | out: 383 | mk_host_if_deinit(&acmd); 384 | printf("STATUS %s\n", mkhi_status(ret)); 385 | return ret; 386 | } 387 | -------------------------------------------------------------------------------- /samples/metee_trc.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2023 Intel Corporation 4 | */ 5 | #include <stdio.h> 6 | 7 | #include <metee.h> 8 | 9 | DEFINE_GUID(GUID_DEVINTERFACE_NULL, 0x00000000, 0x0000, 0x0000, 10 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 11 | 12 | int main(int argc, char* argv[]) 13 | { 14 | TEEHANDLE handle; 15 | TEESTATUS status; 16 | uint32_t trc_val = 0; 17 | struct tee_device_address addr = { 18 | .type = TEE_DEVICE_TYPE_NONE, 19 | .data.path = NULL 20 | }; 21 | 22 | status = TeeInitFull(&handle, &GUID_DEVINTERFACE_NULL, addr, TEE_LOG_LEVEL_VERBOSE, NULL); 23 | if (!TEE_IS_SUCCESS(status)) { 24 | fprintf(stderr, "init failed with status = %u\n", status); 25 | return 1; 26 | } 27 | 28 | status = TeeGetTRC(&handle, &trc_val); 29 | if (!TEE_IS_SUCCESS(status)) { 30 | fprintf(stderr, "TeeGetTRC failed with status = %u\n", status); 31 | } 32 | else { 33 | fprintf(stdout, "TRC = 0x%08X\n", trc_val); 34 | } 35 | 36 | TeeDisconnect(&handle); 37 | return 0; 38 | } -------------------------------------------------------------------------------- /src/Windows/LICENSE.WDK.Ms-LPL: -------------------------------------------------------------------------------- 1 | MICROSOFT LIMITED PUBLIC LICENSE version 1.1 2 | 3 | 4 | This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 5 | 6 | 1. Definitions 7 | The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. A "contribution" is the original software, or any additions or changes to the software. A "contributor" is any person that distributes its contribution under this license. "Licensed patents" are a contributor's patent claims that read directly on its contribution. 8 | 2. Grant of Rights 9 | (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. 10 | (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 11 | 3. Conditions and Limitations 12 | (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. 13 | (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. 14 | (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. 15 | (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. 16 | (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees, or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. 17 | (F) Platform Limitation- The licenses granted in sections 2(A) & 2(B) extend only to the software or derivative works that you create that run on a Microsoft Windows operating system product. -------------------------------------------------------------------------------- /src/Windows/metee.rc.in: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2024 Intel Corporation 4 | */ 5 | // Microsoft Visual C++ generated resource script. 6 | // 7 | 8 | #define APSTUDIO_READONLY_SYMBOLS 9 | ///////////////////////////////////////////////////////////////////////////// 10 | // 11 | // Generated from the TEXTINCLUDE 2 resource. 12 | // 13 | #include <Windows.h> 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | #undef APSTUDIO_READONLY_SYMBOLS 17 | 18 | ///////////////////////////////////////////////////////////////////////////// 19 | // English (United States) resources 20 | 21 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 22 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 23 | 24 | #ifdef APSTUDIO_INVOKED 25 | ///////////////////////////////////////////////////////////////////////////// 26 | // 27 | // TEXTINCLUDE 28 | // 29 | 30 | 1 TEXTINCLUDE 31 | BEGIN 32 | "resource.h\0" 33 | END 34 | 35 | 2 TEXTINCLUDE 36 | BEGIN 37 | "#include ""afxres.h""\r\n" 38 | "\0" 39 | END 40 | 41 | 3 TEXTINCLUDE 42 | BEGIN 43 | "\r\n" 44 | "\0" 45 | END 46 | 47 | #endif // APSTUDIO_INVOKED 48 | 49 | 50 | ///////////////////////////////////////////////////////////////////////////// 51 | // 52 | // Version 53 | // 54 | 55 | VS_VERSION_INFO VERSIONINFO 56 | FILEVERSION @TEE_VERSION_COMM@ 57 | PRODUCTVERSION @TEE_VERSION_COMM@ 58 | FILEFLAGSMASK 0x3fL 59 | #ifdef _DEBUG 60 | FILEFLAGS 0x1L 61 | #else 62 | FILEFLAGS 0x0L 63 | #endif 64 | FILEOS 0x40004L 65 | FILETYPE 0x2L 66 | FILESUBTYPE 0x0L 67 | BEGIN 68 | BLOCK "StringFileInfo" 69 | BEGIN 70 | BLOCK "040904b0" 71 | BEGIN 72 | VALUE "CompanyName", "Intel Corporation" 73 | VALUE "FileDescription", "Intel(R) CSME/GSC HECI Interface Library" 74 | VALUE "FileVersion", "@TEE_VERSION_STRING@" 75 | VALUE "InternalName", "MeTee" 76 | VALUE "LegalCopyright", "Copyright (c) 2014-2024, Intel Corporation." 77 | VALUE "OriginalFilename", "metee.dll" 78 | VALUE "ProductName", "Intel(R) CSME/GSC HECI Interface Library" 79 | VALUE "ProductVersion", "@TEE_VERSION_STRING@" 80 | END 81 | END 82 | BLOCK "VarFileInfo" 83 | BEGIN 84 | VALUE "Translation", 0x409, 1200 85 | END 86 | END 87 | 88 | #endif // English (United States) resources 89 | ///////////////////////////////////////////////////////////////////////////// 90 | 91 | 92 | 93 | #ifndef APSTUDIO_INVOKED 94 | ///////////////////////////////////////////////////////////////////////////// 95 | // 96 | // Generated from the TEXTINCLUDE 3 resource. 97 | // 98 | 99 | 100 | ///////////////////////////////////////////////////////////////////////////// 101 | #endif // not APSTUDIO_INVOKED 102 | 103 | -------------------------------------------------------------------------------- /src/Windows/metee_win.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2014-2025 Intel Corporation 4 | */ 5 | #ifndef __TEELIBWIN_H 6 | #define __TEELIBWIN_H 7 | 8 | #include <Windows.h> 9 | #include <stdbool.h> 10 | #include "metee.h" 11 | 12 | #define CANCEL_TIMEOUT 5000 13 | 14 | enum METEE_CLIENT_STATE 15 | { 16 | METEE_CLIENT_STATE_NONE, 17 | METEE_CLIENT_STATE_CONNECTED, 18 | METEE_CLIENT_STATE_FAILED 19 | }; 20 | 21 | #define METEE_WIN_EVT_IOCTL 0 22 | #define METEE_WIN_EVT_READ 1 23 | #define METEE_WIN_EVT_WRITE 2 24 | #define MAX_EVT 3 25 | 26 | struct METEE_WIN_IMPL 27 | { 28 | HANDLE handle; /**< file descriptor - Handle to the Device File */ 29 | GUID guid; /**< fw client guid */ 30 | LPOVERLAPPED evt[MAX_EVT]; /**< event for executing async */ 31 | bool close_on_exit; /**< close handle on exit */ 32 | enum METEE_CLIENT_STATE state; /**< the client state */ 33 | char *device_path; /**< device path */ 34 | }; 35 | 36 | /********************************************************************* 37 | ** Windows Helper Types ** 38 | **********************************************************************/ 39 | typedef LPOVERLAPPED EVENTHANDLE, *PEVENTHANDLE; 40 | 41 | typedef enum _TEE_OPERATION 42 | { 43 | ReadOperation, 44 | WriteOperation 45 | } TEE_OPERATION; 46 | 47 | /********************************************************************* 48 | ** Windows Helper Functions ** 49 | **********************************************************************/ 50 | TEESTATUS BeginOverlappedInternal(IN TEE_OPERATION operation, 51 | IN PTEEHANDLE handle, IN PVOID buffer, 52 | IN ULONG bufferSize, OUT EVENTHANDLE evt); 53 | TEESTATUS EndOverlapped(IN PTEEHANDLE handle, IN EVENTHANDLE evt, IN DWORD milliseconds, 54 | OUT OPTIONAL LPDWORD pNumberOfBytesTransferred); 55 | TEESTATUS GetDevicePath(IN PTEEHANDLE handle, IN LPCGUID InterfaceGuid, 56 | OUT char *path, IN SIZE_T pathSize); 57 | TEESTATUS GetDeviceKind(IN PTEEHANDLE handle, IN OUT OPTIONAL char *kind, IN OUT size_t *kindSize); 58 | TEESTATUS SendIOCTL(IN PTEEHANDLE handle, IN EVENTHANDLE evt, IN DWORD ioControlCode, IN LPVOID pInBuffer, 59 | IN DWORD inBufferSize, IN LPVOID pOutBuffer, IN DWORD outBufferSize, 60 | OUT LPDWORD pBytesRetuned); 61 | TEESTATUS Win32ErrorToTee(IN DWORD win32Error); 62 | 63 | static inline struct METEE_WIN_IMPL *to_int(PTEEHANDLE _h) 64 | { 65 | return _h ? (struct METEE_WIN_IMPL *)_h->handle : NULL; 66 | } 67 | 68 | #endif /* __TEELIBWIN_H */ 69 | -------------------------------------------------------------------------------- /src/Windows/metee_winhelpers.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2014-2025 Intel Corporation 4 | */ 5 | #include <assert.h> 6 | #include <windows.h> 7 | #include <initguid.h> 8 | #include "helpers.h" 9 | #include "metee.h" 10 | #include "metee_win.h" 11 | #include <cfgmgr32.h> 12 | #include <Objbase.h> 13 | #include <Devpkey.h> 14 | #include <Strsafe.h> 15 | 16 | 17 | /********************************************************************* 18 | ** Windows Helper Functions ** 19 | **********************************************************************/ 20 | void DebugPrintMe(const char* args, ...) 21 | { 22 | char msg[DEBUG_MSG_LEN + 1]; 23 | va_list varl; 24 | va_start(varl, args); 25 | vsprintf_s(msg, DEBUG_MSG_LEN, args, varl); 26 | va_end(varl); 27 | 28 | #ifdef SYSLOG 29 | OutputDebugStringA(msg); 30 | #else 31 | fprintf(stderr, "%s", msg); 32 | #endif /* SYSLOG */ 33 | } 34 | 35 | /* 36 | ** Start Overlapped Operation 37 | ** 38 | ** Parameters: 39 | ** 40 | ** Return: 41 | ** TEE_INVALID_PARAMETER 42 | ** TEE_INTERNAL_ERROR 43 | */ 44 | TEESTATUS BeginOverlappedInternal(IN TEE_OPERATION operation, IN PTEEHANDLE handle, 45 | IN PVOID buffer, IN ULONG bufferSize, OUT EVENTHANDLE evt) 46 | { 47 | TEESTATUS status; 48 | DWORD bytesTransferred= 0; 49 | BOOLEAN optSuccesed = FALSE; 50 | struct METEE_WIN_IMPL *impl_handle = to_int(handle); 51 | 52 | FUNC_ENTRY(handle); 53 | 54 | if (INVALID_HANDLE_VALUE == impl_handle->handle || NULL == buffer || 0 == bufferSize || NULL == evt) { 55 | status = TEE_INVALID_PARAMETER; 56 | ERRPRINT(handle, "One of the parameters was illegal"); 57 | goto Cleanup; 58 | } 59 | 60 | if (operation == ReadOperation) { 61 | if (ReadFile(impl_handle->handle, buffer, bufferSize, &bytesTransferred, evt)) { 62 | optSuccesed = TRUE; 63 | } 64 | } 65 | else if (operation == WriteOperation) { 66 | if (WriteFile(impl_handle->handle, buffer, bufferSize, &bytesTransferred, evt)) { 67 | optSuccesed = TRUE; 68 | } 69 | } 70 | 71 | if (optSuccesed == FALSE) { 72 | DWORD err = GetLastError(); 73 | 74 | if (ERROR_IO_PENDING != err) { 75 | status = Win32ErrorToTee(err); 76 | ERRPRINT(handle, "Error in ReadFile/Write, error: %d\n", err); 77 | } 78 | else { 79 | DBGPRINT(handle, "Pending in ReadFile/Write\n"); 80 | status = TEE_SUCCESS; 81 | } 82 | } 83 | else { 84 | status = TEE_SUCCESS; 85 | } 86 | 87 | Cleanup: 88 | FUNC_EXIT(handle, status); 89 | 90 | return status; 91 | 92 | } 93 | 94 | TEESTATUS EndOverlapped(IN PTEEHANDLE handle, IN EVENTHANDLE evt, IN DWORD milliseconds, 95 | OUT OPTIONAL LPDWORD pNumberOfBytesTransferred) 96 | { 97 | TEESTATUS status; 98 | DWORD err; 99 | DWORD bytesTransferred = 0; 100 | LPDWORD pBytesTransferred = NULL; 101 | struct METEE_WIN_IMPL *impl_handle = to_int(handle); 102 | 103 | FUNC_ENTRY(handle); 104 | 105 | if (INVALID_HANDLE_VALUE == impl_handle->handle || NULL == evt) { 106 | status = TEE_INVALID_PARAMETER; 107 | ERRPRINT(handle, "One of the parameters was illegal\n"); 108 | goto Cleanup; 109 | } 110 | 111 | pBytesTransferred = pNumberOfBytesTransferred ? pNumberOfBytesTransferred : &bytesTransferred; 112 | 113 | // wait for the answer 114 | err = WaitForSingleObject(evt->hEvent, milliseconds); 115 | if (err == WAIT_TIMEOUT) { 116 | status = TEE_TIMEOUT; 117 | ERRPRINT(handle, "WaitForSingleObject timed out!\n"); 118 | goto Cleanup; 119 | } 120 | 121 | if (err != WAIT_OBJECT_0) { 122 | assert(WAIT_FAILED == err); 123 | err = GetLastError(); 124 | status = Win32ErrorToTee(err); 125 | 126 | ERRPRINT(handle, "WaitForSingleObject reported error: %d\n", err); 127 | goto Cleanup; 128 | } 129 | 130 | // last parameter is true b/c if we're here the operation has been completed) 131 | if (!GetOverlappedResult(impl_handle->handle, evt, pBytesTransferred, TRUE)) { 132 | err = GetLastError(); 133 | status = Win32ErrorToTee(err); 134 | ERRPRINT(handle, "Error in GetOverlappedResult, error: %d\n", err); 135 | goto Cleanup; 136 | } 137 | 138 | status = TEE_SUCCESS; //not really needed, but for completeness... 139 | 140 | Cleanup: 141 | FUNC_EXIT(handle, status); 142 | 143 | return status; 144 | } 145 | 146 | /* 147 | ** Return the given Device Path according to it's device GUID 148 | ** 149 | ** Parameters: 150 | ** handle - metee handle 151 | ** InterfaceGuid - Device GUID 152 | ** path - Device path buffer 153 | ** pathSize - Device Path buffer size 154 | ** 155 | ** Return: 156 | ** TEE_DEVICE_NOT_FOUND 157 | ** TEE_INVALID_PARAMETER 158 | ** TEE_INTERNAL_ERROR 159 | */ 160 | TEESTATUS GetDevicePath(IN PTEEHANDLE handle, IN LPCGUID InterfaceGuid, 161 | OUT char *path, IN SIZE_T pathSize) 162 | { 163 | CONFIGRET cr; 164 | char *deviceInterfaceList = NULL; 165 | ULONG deviceInterfaceListLength = 0; 166 | HRESULT hr = E_FAIL; 167 | TEESTATUS status = TEE_INTERNAL_ERROR; 168 | 169 | FUNC_ENTRY(handle); 170 | 171 | if (InterfaceGuid == NULL || path == NULL || pathSize < 1) { 172 | status = TEE_INTERNAL_ERROR; 173 | ERRPRINT(handle, "One of the parameters was illegal"); 174 | goto Cleanup; 175 | } 176 | 177 | path[0] = 0x00; 178 | 179 | cr = CM_Get_Device_Interface_List_SizeA( 180 | &deviceInterfaceListLength, 181 | (LPGUID)InterfaceGuid, 182 | NULL, 183 | CM_GET_DEVICE_INTERFACE_LIST_PRESENT); 184 | if (cr != CR_SUCCESS) { 185 | ERRPRINT(handle, "Error 0x%x retrieving device interface list size.\n", cr); 186 | status = TEE_INTERNAL_ERROR; 187 | goto Cleanup; 188 | } 189 | 190 | if (deviceInterfaceListLength <= 1) { 191 | status = TEE_DEVICE_NOT_FOUND; 192 | ERRPRINT(handle, "SetupDiGetClassDevs returned status %d", GetLastError()); 193 | goto Cleanup; 194 | } 195 | 196 | deviceInterfaceList = (char*)malloc(deviceInterfaceListLength * sizeof(char)); 197 | if (deviceInterfaceList == NULL) { 198 | ERRPRINT(handle, "Error allocating memory for device interface list.\n"); 199 | status = TEE_INTERNAL_ERROR; 200 | goto Cleanup; 201 | } 202 | ZeroMemory(deviceInterfaceList, deviceInterfaceListLength * sizeof(char)); 203 | 204 | cr = CM_Get_Device_Interface_ListA( 205 | (LPGUID)InterfaceGuid, 206 | NULL, 207 | deviceInterfaceList, 208 | deviceInterfaceListLength, 209 | CM_GET_DEVICE_INTERFACE_LIST_PRESENT); 210 | if (cr != CR_SUCCESS) { 211 | ERRPRINT(handle, "Error 0x%x retrieving device interface list.\n", cr); 212 | status = TEE_INTERNAL_ERROR; 213 | goto Cleanup; 214 | } 215 | 216 | hr = StringCchCopyA(path, pathSize, deviceInterfaceList); 217 | if (FAILED(hr)) { 218 | status = TEE_INTERNAL_ERROR; 219 | ERRPRINT(handle, "Error: StringCchCopy failed with HRESULT 0x%x", hr); 220 | goto Cleanup; 221 | } 222 | 223 | status = TEE_SUCCESS; 224 | 225 | Cleanup: 226 | if (deviceInterfaceList != NULL) { 227 | free(deviceInterfaceList); 228 | } 229 | 230 | FUNC_EXIT(handle, status); 231 | 232 | return status; 233 | } 234 | 235 | DEFINE_DEVPROPKEY(DEVPKEY_TeedriverKindString, 236 | 0x3279649a, 0x75b8, 0x4663, 0xab, 0x4f, 0x9d, 0xec, 0x58, 0xc5, 0x58, 0xf5, 237 | DEVPROP_TYPE_STRING); 238 | /* 239 | ** Get device kind implementation 240 | ** 241 | ** Parameters: 242 | ** handle - metee handle 243 | ** kind - pointer to hold device kind, null terminated C string 244 | ** kindSize - size in bytes allocated to kind including null terminator 245 | ** 246 | ** Return: 247 | ** TEE_SUCCESS 248 | ** TEE_INVALID_PARAMETER 249 | ** TEE_INTERNAL_ERROR 250 | */ 251 | TEESTATUS GetDeviceKind(IN PTEEHANDLE handle, IN OUT OPTIONAL char *kind, IN OUT size_t *kindSize) 252 | { 253 | CONFIGRET cr; 254 | DEVPROPTYPE prop_type = 0; 255 | ULONG prop_size = 0; 256 | DEVINST devInstHandle; 257 | WCHAR instance_id[MAX_PATH] = { 0 }; 258 | WCHAR* device_path_w = NULL; 259 | WCHAR* kind_w = NULL; 260 | size_t converted_chars; 261 | errno_t err; 262 | 263 | TEESTATUS status = TEE_INTERNAL_ERROR; 264 | 265 | if (NULL == handle) { 266 | return TEE_INVALID_PARAMETER; 267 | } 268 | 269 | struct METEE_WIN_IMPL* impl_handle = to_int(handle); 270 | 271 | FUNC_ENTRY(handle); 272 | 273 | size_t device_path_len = strlen(impl_handle->device_path) + 1; 274 | size_t device_path_size = device_path_len * sizeof(WCHAR); 275 | device_path_w = (WCHAR*)malloc(device_path_size); 276 | if (NULL == device_path_w) { 277 | status = TEE_INTERNAL_ERROR; 278 | ERRPRINT(handle, "Error allocating memory for device path.\n"); 279 | goto Cleanup; 280 | } 281 | converted_chars = 0; 282 | mbstowcs_s(&converted_chars, device_path_w, device_path_len, impl_handle->device_path, _TRUNCATE); 283 | if (converted_chars != device_path_len) { 284 | status = TEE_INTERNAL_ERROR; 285 | ERRPRINT(handle, "Error converting device path to wide.\n"); 286 | goto Cleanup; 287 | } 288 | 289 | prop_size = MAX_PATH; 290 | cr = CM_Get_Device_Interface_PropertyW(device_path_w, &DEVPKEY_Device_InstanceId, &prop_type, (PBYTE)instance_id, &prop_size, 0); 291 | if (cr != CR_SUCCESS) { 292 | ERRPRINT(handle, "CM_Get_Device_Interface_Property: %d\n", cr); 293 | status = TEE_INTERNAL_ERROR; 294 | goto Cleanup; 295 | } 296 | if (DEVPROP_TYPE_STRING != prop_type) 297 | { 298 | ERRPRINT(handle, "Invalid property type %d\n", prop_type); 299 | status = TEE_INTERNAL_ERROR; 300 | goto Cleanup; 301 | } 302 | 303 | cr = CM_Locate_DevNodeW(&devInstHandle, &instance_id[0], CM_LOCATE_DEVNODE_NORMAL); 304 | if (cr != CR_SUCCESS) { 305 | ERRPRINT(handle, "CM_Locate_DevNode: %d\n", cr); 306 | status = TEE_INTERNAL_ERROR; 307 | goto Cleanup; 308 | } 309 | 310 | prop_size = 0; 311 | cr = CM_Get_DevNode_PropertyW(devInstHandle, &DEVPKEY_TeedriverKindString, &prop_type, NULL, &prop_size, 0); 312 | if (cr == CR_NO_SUCH_VALUE) { 313 | DBGPRINT(handle, "CM_Get_DevNode_Property: kind not found\n"); 314 | status = TEE_NOTSUPPORTED; 315 | goto Cleanup; 316 | } 317 | if (cr != CR_BUFFER_SMALL) { 318 | ERRPRINT(handle, "CM_Get_DevNode_Property: %d %d\n", cr, prop_size); 319 | status = TEE_INTERNAL_ERROR; 320 | goto Cleanup; 321 | } 322 | kind_w = (WCHAR*)malloc(prop_size); 323 | if (NULL == kind_w) { 324 | status = TEE_INTERNAL_ERROR; 325 | ERRPRINT(handle, "Error allocating memory for driver kind wide.\n"); 326 | goto Cleanup; 327 | } 328 | cr = CM_Get_DevNode_PropertyW(devInstHandle, &DEVPKEY_TeedriverKindString, &prop_type, (PBYTE)kind_w, &prop_size, 0); 329 | if (cr != CR_SUCCESS) { 330 | ERRPRINT(handle, "CM_Get_DevNode_Property: %d %d\n", cr, prop_size); 331 | status = TEE_INTERNAL_ERROR; 332 | goto Cleanup; 333 | } 334 | if (*kindSize < prop_size) { 335 | ERRPRINT(handle, "Insufficient buffer %d %d\n", *kindSize, prop_size); 336 | *kindSize = prop_size; 337 | status = TEE_INSUFFICIENT_BUFFER; 338 | goto Cleanup; 339 | } 340 | /* 341 | safe implementation of the conversion function 342 | handles NULL input/output buffer values and output buffer overrun 343 | */ 344 | err = wcstombs_s(&converted_chars, kind, *kindSize, kind_w, _TRUNCATE); 345 | if (err != 0) { 346 | ERRPRINT(handle, "convert to multi-byte error %d\n", err); 347 | if (err == STRUNCATE || err == EINVAL) { 348 | *kindSize = prop_size; 349 | status = TEE_INSUFFICIENT_BUFFER; 350 | } else { 351 | status = TEE_INTERNAL_ERROR; 352 | } 353 | goto Cleanup; 354 | } 355 | *kindSize = converted_chars; 356 | status = TEE_SUCCESS; 357 | 358 | Cleanup: 359 | free(kind_w); 360 | free(device_path_w); 361 | FUNC_EXIT(handle, status); 362 | return status; 363 | } 364 | 365 | TEESTATUS SendIOCTL(IN PTEEHANDLE handle, IN EVENTHANDLE evt, IN DWORD ioControlCode, 366 | IN LPVOID pInBuffer, IN DWORD inBufferSize, 367 | IN LPVOID pOutBuffer, IN DWORD outBufferSize, OUT LPDWORD pBytesRetuned) 368 | { 369 | TEESTATUS status; 370 | DWORD err; 371 | struct METEE_WIN_IMPL *impl_handle = to_int(handle); 372 | 373 | FUNC_ENTRY(handle); 374 | 375 | if (INVALID_HANDLE_VALUE == impl_handle->handle || NULL == pBytesRetuned) { 376 | status = ERROR_INVALID_PARAMETER; 377 | ERRPRINT(handle, "One of the parameters was illegal"); 378 | goto Cleanup; 379 | } 380 | 381 | if (!DeviceIoControl(impl_handle->handle, ioControlCode, 382 | pInBuffer, inBufferSize, 383 | pOutBuffer, outBufferSize, 384 | pBytesRetuned, evt)) { 385 | 386 | err = GetLastError(); 387 | // it's ok to get an error here, because it's overlapped 388 | if (ERROR_IO_PENDING != err) { 389 | ERRPRINT(handle, "Error in DeviceIoControl, error: %d\n", err); 390 | status = Win32ErrorToTee(err); 391 | goto Cleanup; 392 | } 393 | } 394 | 395 | 396 | if (!GetOverlappedResult(impl_handle->handle, evt, pBytesRetuned, TRUE)) { 397 | err = GetLastError(); 398 | ERRPRINT(handle, "Error in GetOverlappedResult, error: %d\n", err); 399 | status = Win32ErrorToTee(err); 400 | goto Cleanup; 401 | } 402 | 403 | status = TEE_SUCCESS; 404 | 405 | Cleanup: 406 | 407 | FUNC_EXIT(handle, status); 408 | 409 | return status; 410 | } 411 | 412 | TEESTATUS Win32ErrorToTee(IN DWORD win32Error) 413 | { 414 | switch (win32Error) { 415 | case ERROR_INVALID_HANDLE: 416 | return TEE_INVALID_PARAMETER; 417 | case ERROR_INSUFFICIENT_BUFFER: 418 | return TEE_INSUFFICIENT_BUFFER; 419 | case ERROR_GEN_FAILURE: 420 | return TEE_UNABLE_TO_COMPLETE_OPERATION; 421 | case ERROR_DEVICE_NOT_CONNECTED: 422 | return TEE_DEVICE_NOT_READY; 423 | case ERROR_NOT_FOUND: 424 | return TEE_CLIENT_NOT_FOUND; 425 | case ERROR_ACCESS_DENIED: 426 | return TEE_PERMISSION_DENIED; 427 | case ERROR_OPERATION_ABORTED: 428 | return TEE_UNABLE_TO_COMPLETE_OPERATION; 429 | default: 430 | return TEE_INTERNAL_ERROR; 431 | } 432 | } 433 | -------------------------------------------------------------------------------- /src/Windows/public.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2014-2023 Intel Corporation 4 | */ 5 | /*++ 6 | 7 | Module Name: 8 | 9 | public.h 10 | 11 | Abstract: 12 | 13 | This module contains the common declarations shared by driver 14 | and user applications. 15 | 16 | Environment: 17 | 18 | user and kernel 19 | 20 | --*/ 21 | 22 | #ifndef __PUBLIC_H 23 | #define __PUBLIC_H 24 | 25 | // 26 | // Define an Interface Guid so that app can find the device and talk to it. 27 | // 28 | 29 | DEFINE_GUID(GUID_DEVINTERFACE_HECI, 0xE2D1FF34, 0x3458, 0x49A9, 30 | 0x88, 0xDA, 0x8E, 0x69, 0x15, 0xCE, 0x9B, 0xE5); 31 | // {1b6cc5ff-1bba-4a0d-9899-13427aa05156} 32 | 33 | #define FILE_DEVICE_HECI 0x8000 34 | 35 | // Define Interface reference/dereference routines for 36 | // Interfaces exported by IRP_MN_QUERY_INTERFACE 37 | 38 | #define IOCTL_TEEDRIVER_GET_VERSION \ 39 | CTL_CODE(FILE_DEVICE_HECI, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS|FILE_WRITE_ACCESS) 40 | #define IOCTL_TEEDRIVER_CONNECT_CLIENT \ 41 | CTL_CODE(FILE_DEVICE_HECI, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS|FILE_WRITE_ACCESS) 42 | #define IOCTL_TEEDRIVER_GET_FW_STS \ 43 | CTL_CODE(FILE_DEVICE_HECI, 0x803, METHOD_BUFFERED, FILE_READ_ACCESS|FILE_WRITE_ACCESS) 44 | #define IOCTL_TEEDRIVER_GET_TRC \ 45 | CTL_CODE(FILE_DEVICE_HECI, 0x813, METHOD_BUFFERED, FILE_READ_ACCESS|FILE_WRITE_ACCESS) 46 | 47 | #pragma pack(1) 48 | typedef struct _FW_CLIENT 49 | { 50 | UINT32 MaxMessageLength; 51 | UINT8 ProtocolVersion; 52 | } FW_CLIENT; 53 | #pragma pack( ) 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/linux/LICENSE.libmei: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * This source is provided under BSD license. 3 | * 4 | * BSD LICENSE 5 | * 6 | * Copyright(c) 2013 - 2019 Intel Corporation. All rights reserved. 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in 17 | * the documentation and/or other materials provided with the 18 | * distribution. 19 | * * Neither the name Intel Corporation nor the names of its 20 | * contributors may be used to endorse or promote products derived 21 | * from this software without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | * 35 | -------------------------------------------------------------------------------- /src/linux/include/linux/mei.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ 2 | /* 3 | * Copyright(c) 2003-2015 Intel Corporation. All rights reserved. 4 | * Intel Management Engine Interface (Intel MEI) Linux driver 5 | * Intel MEI Interface Header 6 | */ 7 | #ifndef _LINUX_MEI_H 8 | #define _LINUX_MEI_H 9 | 10 | #include <linux/uuid.h> 11 | 12 | /* 13 | * This IOCTL is used to associate the current file descriptor with a 14 | * FW Client (given by UUID). This opens a communication channel 15 | * between a host client and a FW client. From this point every read and write 16 | * will communicate with the associated FW client. 17 | * Only in close() (file_operation release()) the communication between 18 | * the clients is disconnected 19 | * 20 | * The IOCTL argument is a struct with a union that contains 21 | * the input parameter and the output parameter for this IOCTL. 22 | * 23 | * The input parameter is UUID of the FW Client. 24 | * The output parameter is the properties of the FW client 25 | * (FW protocol version and max message size). 26 | * 27 | */ 28 | #define IOCTL_MEI_CONNECT_CLIENT \ 29 | _IOWR('H', 0x01, struct mei_connect_client_data) 30 | 31 | /* 32 | * Intel MEI client information struct 33 | */ 34 | struct mei_client { 35 | __u32 max_msg_length; 36 | __u8 protocol_version; 37 | __u8 reserved[3]; 38 | }; 39 | 40 | /* 41 | * IOCTL Connect Client Data structure 42 | */ 43 | struct mei_connect_client_data { 44 | union { 45 | uuid_le in_client_uuid; 46 | struct mei_client out_client_properties; 47 | }; 48 | }; 49 | 50 | /** 51 | * DOC: set and unset event notification for a connected client 52 | * 53 | * The IOCTL argument is 1 for enabling event notification and 0 for 54 | * disabling the service 55 | * Return: -EOPNOTSUPP if the devices doesn't support the feature 56 | */ 57 | #define IOCTL_MEI_NOTIFY_SET _IOW('H', 0x02, __u32) 58 | 59 | /** 60 | * DOC: retrieve notification 61 | * 62 | * The IOCTL output argument is 1 if an event was is pending and 0 otherwise 63 | * the ioctl has to be called in order to acknowledge pending event 64 | * 65 | * Return: -EOPNOTSUPP if the devices doesn't support the feature 66 | */ 67 | #define IOCTL_MEI_NOTIFY_GET _IOR('H', 0x03, __u32) 68 | 69 | /** 70 | * struct mei_connect_client_vtag - mei client information struct with vtag 71 | * 72 | * @in_client_uuid: UUID of client to connect 73 | * @vtag: virtual tag 74 | * @reserved: reserved for future use 75 | */ 76 | struct mei_connect_client_vtag { 77 | uuid_le in_client_uuid; 78 | __u8 vtag; 79 | __u8 reserved[3]; 80 | }; 81 | 82 | /** 83 | * struct mei_connect_client_data_vtag - IOCTL connect data union 84 | * 85 | * @connect: input connect data 86 | * @out_client_properties: output client data 87 | */ 88 | struct mei_connect_client_data_vtag { 89 | union { 90 | struct mei_connect_client_vtag connect; 91 | struct mei_client out_client_properties; 92 | }; 93 | }; 94 | 95 | /** 96 | * DOC: 97 | * This IOCTL is used to associate the current file descriptor with a 98 | * FW Client (given by UUID), and virtual tag (vtag). 99 | * The IOCTL opens a communication channel between a host client and 100 | * a FW client on a tagged channel. From this point on, every read 101 | * and write will communicate with the associated FW client with 102 | * on the tagged channel. 103 | * Upone close() the communication is terminated. 104 | * 105 | * The IOCTL argument is a struct with a union that contains 106 | * the input parameter and the output parameter for this IOCTL. 107 | * 108 | * The input parameter is UUID of the FW Client, a vtag [0,255] 109 | * The output parameter is the properties of the FW client 110 | * (FW protocool version and max message size). 111 | * 112 | * Clients that do not support tagged connection 113 | * will respond with -EOPNOTSUPP. 114 | */ 115 | #define IOCTL_MEI_CONNECT_CLIENT_VTAG \ 116 | _IOWR('H', 0x04, struct mei_connect_client_data_vtag) 117 | 118 | #endif /* _LINUX_MEI_H */ 119 | -------------------------------------------------------------------------------- /src/linux/libmei.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: BSD-3-Clause 3 | * 4 | * Copyright(c) 2013 - 2025 Intel Corporation. All rights reserved. 5 | * 6 | * Intel Management Engine Interface (Intel MEI) Library 7 | */ 8 | /*! \file libmei.h 9 | * \brief mei library API 10 | */ 11 | #ifndef __LIBMEI_H__ 12 | #define __LIBMEI_H__ 13 | 14 | #include <linux/uuid.h> 15 | #include <linux/mei.h> 16 | #include <stdbool.h> 17 | #include <stdint.h> 18 | #include <unistd.h> 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif /* __cplusplus */ 23 | 24 | /*! Library API version encode helper 25 | */ 26 | #define MEI_ENCODE_VERSION(major, minor) ((major) << 16 | (minor) << 8) 27 | 28 | /*! Library API version 29 | */ 30 | #define LIBMEI_API_VERSION MEI_ENCODE_VERSION(1, 6) 31 | 32 | /*! Get current supported library API version 33 | * 34 | * \return version value 35 | */ 36 | unsigned int mei_get_api_version(void); 37 | 38 | /*! ME client connection state 39 | */ 40 | enum mei_cl_state { 41 | MEI_CL_STATE_ZERO = 0, /**< reserved */ 42 | MEI_CL_STATE_INTIALIZED = 1, /**< client is initialized (typo) */ 43 | MEI_CL_STATE_INITIALIZED = 1, /**< client is initialized */ 44 | MEI_CL_STATE_CONNECTED, /**< client is connected */ 45 | MEI_CL_STATE_DISCONNECTED, /**< client is disconnected */ 46 | MEI_CL_STATE_NOT_PRESENT, /**< client with GUID is not present in the system */ 47 | MEI_CL_STATE_VERSION_MISMATCH, /**< client version not supported */ 48 | MEI_CL_STATE_ERROR, /**< client is in error state */ 49 | }; 50 | 51 | /*! log level 52 | */ 53 | enum mei_log_level { 54 | MEI_LOG_LEVEL_QUIET = 0, /**< no log prints */ 55 | MEI_LOG_LEVEL_ERROR = 1, /**< error log prints */ 56 | MEI_LOG_LEVEL_VERBOSE = 2 /**< verbose log prints */ 57 | }; 58 | 59 | /*! log callback function format 60 | */ 61 | typedef void(*mei_log_callback)(bool is_error, const char* fmt, ...); 62 | 63 | /*! Structure to store connection data 64 | */ 65 | struct mei { 66 | uuid_le guid; /**< client UUID */ 67 | unsigned int buf_size; /**< maximum buffer size supported by client*/ 68 | unsigned char prot_ver; /**< protocol version */ 69 | int fd; /**< connection file descriptor */ 70 | int state; /**< client connection state */ 71 | int last_err; /**< saved errno */ 72 | bool notify_en; /**< notification is enabled */ 73 | enum mei_log_level log_level; /**< libmei log level */ 74 | bool close_on_exit; /**< close handle on deinit */ 75 | char *device; /**< device name */ 76 | uint8_t vtag; /**< vtag used in communication */ 77 | mei_log_callback log_callback; /**< Log callback */ 78 | }; 79 | 80 | /*! Default name of mei device 81 | */ 82 | #define MEI_DEFAULT_DEVICE_NAME "mei0" 83 | 84 | /*! Default path to mei device 85 | */ 86 | #define MEI_DEFAULT_DEVICE_PREFIX "/dev/" 87 | #define MEI_DEFAULT_DEVICE (MEI_DEFAULT_DEVICE_PREFIX MEI_DEFAULT_DEVICE_NAME) 88 | 89 | /*! Allocate and initialize me handle structure 90 | * 91 | * \param device device path, set MEI_DEFAULT_DEVICE to use default 92 | * \param guid UUID/GUID of associated mei client 93 | * \param req_protocol_version minimal required protocol version, 0 for any 94 | * \param verbose print verbose output to console 95 | * \return me handle to the mei device. All subsequent calls to the lib's functions 96 | * must be with this handle. NULL on failure. 97 | */ 98 | struct mei *mei_alloc(const char *device, const uuid_le *guid, 99 | unsigned char req_protocol_version, bool verbose); 100 | 101 | /*! Allocate and initialize me handle structure 102 | * 103 | * \param fd open file descriptor of MEI device 104 | * \param guid UUID/GUID of associated mei client 105 | * \param req_protocol_version minimal required protocol version, 0 for any 106 | * \param verbose print verbose output to console 107 | * \return me handle to the mei device. All subsequent calls to the lib's functions 108 | * must be with this handle. NULL on failure. 109 | */ 110 | struct mei *mei_alloc_fd(int fd, const uuid_le *guid, 111 | unsigned char req_protocol_version, bool verbose); 112 | 113 | /*! Free me handle structure 114 | * 115 | * \param me The mei handle 116 | */ 117 | void mei_free(struct mei *me); 118 | 119 | /*! Initializes a mei connection 120 | * 121 | * \param me A handle to the mei device. All subsequent calls to the lib's functions 122 | * must be with this handle 123 | * \param device device path, set MEI_DEFAULT_DEVICE to use default 124 | * \param guid UUID/GUID of associated mei client 125 | * \param req_protocol_version minimal required protocol version, 0 for any 126 | * \param verbose print verbose output to a console 127 | * \return 0 if successful, otherwise error code 128 | */ 129 | int mei_init(struct mei *me, const char *device, const uuid_le *guid, 130 | unsigned char req_protocol_version, bool verbose); 131 | 132 | /*! Initializes a mei connection with log callback 133 | * 134 | * \param me A handle to the mei device. All subsequent calls to the lib's functions 135 | * must be with this handle 136 | * \param device device path, set MEI_DEFAULT_DEVICE to use default 137 | * \param guid GUID of associated mei client 138 | * \param req_protocol_version minimal required protocol version, 0 for any 139 | * \param verbose print verbose output to a console 140 | * \param log_callback pointer to function to run for log write, set NULL to use built-in function 141 | * \return 0 if successful, otherwise error code 142 | */ 143 | int mei_init_with_log(struct mei *me, const char *device, const uuid_le *guid, 144 | unsigned char req_protocol_version, bool verbose, 145 | mei_log_callback log_callback); 146 | 147 | /*! Initializes a mei connection 148 | * 149 | * \param me A handle to the mei device. All subsequent calls to the lib's functions 150 | * must be with this handle 151 | * \param fd open file descriptor of MEI device 152 | * \param guid UUID/GUID of associated mei client 153 | * \param req_protocol_version minimal required protocol version, 0 for any 154 | * \param verbose print verbose output to a console 155 | * \return 0 if successful, otherwise error code 156 | */ 157 | int mei_init_fd(struct mei *me, int fd, const uuid_le *guid, 158 | unsigned char req_protocol_version, bool verbose); 159 | 160 | 161 | /*! Closes the session to me driver 162 | * Make sure that you call this function as soon as you are done with the device, 163 | * as other clients might be blocked until the session is closed. 164 | * 165 | * \param me The mei handle 166 | */ 167 | void mei_deinit(struct mei *me); 168 | 169 | /*! Open mei device and starts a session with a mei client 170 | * If the application requested specific minimal protocol version 171 | * and the client does not support that version than 172 | * the handle state will be set to MEI_CL_STATE_VERSION_MISMATCH 173 | * but connection will be established 174 | * 175 | * \param me The mei handle 176 | * \return 0 if successful, otherwise error code 177 | */ 178 | int mei_connect(struct mei *me); 179 | 180 | /*! Open mei device and starts a session with a mei client 181 | * Provide given vtag as session parameter. 182 | * If the application requested specific minimal protocol version 183 | * and the client does not support that version than 184 | * the handle state will be set to MEI_CL_STATE_VERSION_MISMATCH 185 | * but connection will be established 186 | * 187 | * \param me The mei handle 188 | * \param vtag The vtag value 189 | * \return 0 if successful, otherwise error code 190 | */ 191 | int mei_connect_vtag(struct mei *me, uint8_t vtag); 192 | 193 | /*! Setup mei connection to non block 194 | * 195 | * \param me The mei handle 196 | * \return 0 if successful, otherwise error code 197 | */ 198 | int mei_set_nonblock(struct mei *me); 199 | 200 | /*! return file descriptor to opened handle 201 | * 202 | * \param me The mei handle 203 | * \return file descriptor or error 204 | */ 205 | int mei_get_fd(struct mei *me); 206 | 207 | /*! Read data from the mei device. 208 | * 209 | * \param me The mei handle 210 | * \param buffer A pointer to a buffer that receives the data read from the mei device. 211 | * \param len The number of bytes to be read. 212 | * \return number of byte read if successful, otherwise error code 213 | */ 214 | ssize_t mei_recv_msg(struct mei *me, unsigned char *buffer, size_t len); 215 | 216 | /*! Writes the specified buffer to the mei device. 217 | * 218 | * \param me The mei handle 219 | * \param buffer A pointer to the buffer containing the data to be written to the mei device. 220 | * \param len The number of bytes to be written. 221 | * \return number of bytes written if successful, otherwise error code 222 | */ 223 | ssize_t mei_send_msg(struct mei *me, const unsigned char *buffer, size_t len); 224 | 225 | /*! Request to Enable or Disable Event Notification 226 | * 227 | * \param me The mei handle 228 | * \param enable A boolean to enable or disable event notification 229 | * \return 0 if successful, otherwise error code 230 | */ 231 | int mei_notification_request(struct mei *me, bool enable); 232 | 233 | /*! Acknowledge an event and enable further notification 234 | * notification events are signaled as priority events (POLLPRI) on select/poll 235 | * 236 | * \param me The mei handle 237 | * \return 0 if successful, otherwise error code. -ENOTSUPP is returned 238 | * in case the event notification was not enabled 239 | */ 240 | int mei_notification_get(struct mei *me); 241 | 242 | /*! Obtains FW status of device 243 | * 244 | * \param me The mei handle 245 | * \param fwsts_num The FW status register number (0-5). 246 | * \param fwsts FW status to fill 247 | * \return 0 if successful, otherwise error code 248 | */ 249 | int mei_fwstatus(struct mei *me, uint32_t fwsts_num, uint32_t *fwsts); 250 | 251 | /*! Obtains TRC status of device 252 | * 253 | * \param me The mei handle 254 | * \param trc_val TRC value fill 255 | * \return 0 if successful, otherwise error code 256 | */ 257 | int mei_gettrc(struct mei *me, uint32_t *trc_val); 258 | 259 | /*! Obtains device kind 260 | * 261 | * \param me The mei handle 262 | * \param kind buffer to fill with device kind null terminated string, may be NULL. 263 | * \param kind_size Pointer to kind buffer size in bytes, updated to number of bytes filled in buffer, including null character, on out. 264 | * If buffer is NULL, required size is returned anyway. 265 | * \return 0 if successful, otherwise error code 266 | */ 267 | int mei_getkind(struct mei *me, char *kind, size_t *kind_size); 268 | 269 | /*! Set log level 270 | * 271 | * \param me The mei handle 272 | * \param log_level log level to set 273 | * \return previous log level 274 | */ 275 | uint32_t mei_set_log_level(struct mei *me, uint32_t log_level); 276 | 277 | /*! Retrieve current log level 278 | * 279 | * \param me The mei handle 280 | * \return current log level 281 | */ 282 | uint32_t mei_get_log_level(const struct mei *me); 283 | 284 | /*! Set log callback 285 | * 286 | * \param me The mei handle 287 | * \param log_callback pointer to function to run for log write, set NULL to use built-in function 288 | * \return 0 if successful, otherwise error code. 289 | */ 290 | int mei_set_log_callback(struct mei *me, mei_log_callback log_callback); 291 | 292 | #ifdef __cplusplus 293 | } 294 | #endif /* __cplusplus */ 295 | 296 | #endif /* __LIBMEI_H__ */ 297 | -------------------------------------------------------------------------------- /src/linux/metee_linux.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2014-2025 Intel Corporation 4 | */ 5 | #include <errno.h> 6 | #include <fcntl.h> 7 | #include <libmei.h> 8 | #include <limits.h> 9 | #include <linux/mei.h> 10 | #include <stdbool.h> 11 | #include <stdint.h> 12 | #include <stdio.h> 13 | #include <stdlib.h> 14 | #include <string.h> 15 | #include <sys/ioctl.h> 16 | #include <poll.h> 17 | #include <unistd.h> 18 | 19 | #include "metee.h" 20 | #include "helpers.h" 21 | 22 | #define MAX_FW_STATUS_NUM 5 23 | #define CANCEL_PIPES_NUM 2 24 | 25 | struct metee_linux_intl { 26 | struct mei me; 27 | int cancel_pipe[CANCEL_PIPES_NUM]; 28 | }; 29 | 30 | /* use inline function instead of macro to avoid -Waddress warning in GCC */ 31 | static inline struct mei *to_mei(PTEEHANDLE _h) __attribute__((always_inline)); 32 | static inline struct mei *to_mei(PTEEHANDLE _h) 33 | { 34 | return _h ? &((struct metee_linux_intl *)_h->handle)->me : NULL; 35 | } 36 | 37 | /* use inline function instead of macro to avoid -Waddress warning in GCC */ 38 | static inline struct metee_linux_intl *to_intl(PTEEHANDLE _h) __attribute__((always_inline)); 39 | static inline struct metee_linux_intl *to_intl(PTEEHANDLE _h) 40 | { 41 | return _h ? (struct metee_linux_intl *)_h->handle : NULL; 42 | } 43 | 44 | static inline int __mei_select(struct mei *me, int pipe_fd, 45 | bool on_read, int timeout) 46 | { 47 | int rv; 48 | struct pollfd pfd[2]; 49 | pfd[0].fd = me->fd; 50 | pfd[0].events = (on_read) ? POLLIN : POLLOUT; 51 | pfd[1].fd = pipe_fd; 52 | pfd[1].events = POLLIN; 53 | 54 | errno = 0; 55 | rv = poll(pfd, 2, timeout); 56 | if (rv < 0) 57 | return -errno; 58 | if (rv == 0) 59 | return -ETIME; 60 | if (pfd[1].revents != 0) 61 | return -ECANCELED; 62 | return 0; 63 | } 64 | 65 | static inline TEESTATUS errno2status(ssize_t err) 66 | { 67 | switch (err) { 68 | case 0 : return TEE_SUCCESS; 69 | case -ENOTTY: return TEE_CLIENT_NOT_FOUND; 70 | case -EBUSY : return TEE_BUSY; 71 | case -ENODEV: return TEE_DISCONNECTED; 72 | case -ETIME : return TEE_TIMEOUT; 73 | case -EACCES: return TEE_PERMISSION_DENIED; 74 | case -EOPNOTSUPP: return TEE_NOTSUPPORTED; 75 | case -ECANCELED: return TEE_UNABLE_TO_COMPLETE_OPERATION; 76 | case -ENOSPC: return TEE_INSUFFICIENT_BUFFER; 77 | default : return TEE_INTERNAL_ERROR; 78 | } 79 | } 80 | 81 | static inline TEESTATUS errno2status_init(ssize_t err) 82 | { 83 | switch (err) { 84 | case 0 : return TEE_SUCCESS; 85 | case -ENOENT: return TEE_DEVICE_NOT_FOUND; 86 | case -ENAMETOOLONG: return TEE_DEVICE_NOT_FOUND; 87 | case -EBUSY : return TEE_BUSY; 88 | case -ENODEV: return TEE_DEVICE_NOT_READY; 89 | case -ETIME : return TEE_TIMEOUT; 90 | case -EACCES: return TEE_PERMISSION_DENIED; 91 | default : return TEE_INTERNAL_ERROR; 92 | } 93 | } 94 | 95 | TEESTATUS TEEAPI TeeInitFull(IN OUT PTEEHANDLE handle, IN const GUID* guid, 96 | IN const struct tee_device_address device, 97 | IN uint32_t log_level, IN OPTIONAL TeeLogCallback log_callback) 98 | { 99 | struct metee_linux_intl *intl; 100 | TEESTATUS status; 101 | int rc; 102 | bool verbose = (log_level == TEE_LOG_LEVEL_VERBOSE); 103 | 104 | if (guid == NULL || handle == NULL) { 105 | return TEE_INVALID_PARAMETER; 106 | } 107 | 108 | __tee_init_handle(handle); 109 | handle->log_level = (log_level >= TEE_LOG_LEVEL_MAX) ? TEE_LOG_LEVEL_VERBOSE : log_level; 110 | handle->log_callback = log_callback; 111 | 112 | FUNC_ENTRY(handle); 113 | 114 | if (log_level >= TEE_LOG_LEVEL_MAX) { 115 | ERRPRINT(handle, "LogLevel %u is too big.\n", log_level); 116 | status = TEE_INVALID_PARAMETER; 117 | goto End; 118 | } 119 | switch (device.type) { 120 | case TEE_DEVICE_TYPE_NONE: 121 | if (device.data.path != NULL) { 122 | ERRPRINT(handle, "Path is not NULL.\n"); 123 | status = TEE_INVALID_PARAMETER; 124 | goto End; 125 | } 126 | break; 127 | case TEE_DEVICE_TYPE_PATH: 128 | if (device.data.path == NULL) { 129 | ERRPRINT(handle, "Path is NULL.\n"); 130 | status = TEE_INVALID_PARAMETER; 131 | goto End; 132 | } 133 | break; 134 | case TEE_DEVICE_TYPE_HANDLE: 135 | if (device.data.handle == TEE_INVALID_DEVICE_HANDLE) { 136 | ERRPRINT(handle, "Handle is invalid.\n"); 137 | status = TEE_INVALID_PARAMETER; 138 | goto End; 139 | } 140 | break; 141 | case TEE_DEVICE_TYPE_GUID: 142 | default: 143 | ERRPRINT(handle, "Wrong device type %u.\n", device.type); 144 | status = TEE_INVALID_PARAMETER; 145 | goto End; 146 | } 147 | 148 | intl = malloc(sizeof(struct metee_linux_intl)); 149 | if (!intl) { 150 | ERRPRINT(handle, "Cannot alloc intl structure\n"); 151 | status = TEE_INTERNAL_ERROR; 152 | goto End; 153 | } 154 | 155 | switch (device.type) { 156 | case TEE_DEVICE_TYPE_NONE: 157 | rc = mei_init_with_log(&intl->me, MEI_DEFAULT_DEVICE, 158 | (uuid_le*)guid, 0, verbose, log_callback); 159 | break; 160 | case TEE_DEVICE_TYPE_PATH: 161 | rc = mei_init_with_log(&intl->me, device.data.path, 162 | (uuid_le*)guid, 0, verbose, log_callback); 163 | break; 164 | case TEE_DEVICE_TYPE_HANDLE: 165 | rc = mei_init_fd(&intl->me, device.data.handle, (uuid_le*)guid, 0, verbose); 166 | if (!rc) { 167 | mei_set_log_callback(&intl->me, log_callback); 168 | mei_set_log_level(&intl->me, verbose); 169 | } 170 | break; 171 | default: 172 | rc = -EFAULT; 173 | break; 174 | } 175 | if (rc) { 176 | free(intl); 177 | ERRPRINT(handle, "Cannot init mei, rc = %d\n", rc); 178 | status = errno2status_init(rc); 179 | goto End; 180 | } 181 | rc = pipe(intl->cancel_pipe); 182 | if (rc) { 183 | mei_deinit(&intl->me); 184 | free(intl); 185 | ERRPRINT(handle, "Cannot init mei, rc = %d\n", rc); 186 | status = errno2status_init(rc); 187 | goto End; 188 | } 189 | handle->handle = intl; 190 | 191 | status = TEE_SUCCESS; 192 | 193 | End: 194 | return status; 195 | } 196 | 197 | TEESTATUS TEEAPI TeeInit(IN OUT PTEEHANDLE handle, IN const GUID* guid, 198 | IN OPTIONAL const char* device) 199 | { 200 | struct tee_device_address addr; 201 | 202 | addr.type = (device) ? TEE_DEVICE_TYPE_PATH : TEE_DEVICE_TYPE_NONE; 203 | addr.data.path = device; 204 | 205 | return TeeInitFull(handle, guid, addr, TEE_DEFAULT_LOG_LEVEL, NULL); 206 | } 207 | 208 | TEESTATUS TEEAPI TeeInitHandle(IN OUT PTEEHANDLE handle, IN const GUID *guid, 209 | IN const TEE_DEVICE_HANDLE device_handle) 210 | { 211 | struct tee_device_address addr; 212 | 213 | addr.type = TEE_DEVICE_TYPE_HANDLE; 214 | addr.data.handle = device_handle; 215 | 216 | return TeeInitFull(handle, guid, addr, TEE_DEFAULT_LOG_LEVEL, NULL); 217 | } 218 | 219 | TEESTATUS TEEAPI TeeConnect(IN OUT PTEEHANDLE handle) 220 | { 221 | struct mei *me = to_mei(handle); 222 | TEESTATUS status; 223 | int rc; 224 | 225 | if (!handle) { 226 | return TEE_INVALID_PARAMETER; 227 | } 228 | 229 | FUNC_ENTRY(handle); 230 | 231 | if (!me) { 232 | ERRPRINT(handle, "One of the parameters was illegal\n"); 233 | status = TEE_INVALID_PARAMETER; 234 | goto End; 235 | } 236 | 237 | rc = mei_connect(me); 238 | if (rc) { 239 | ERRPRINT(handle, "Cannot establish a handle to the Intel MEI driver\n"); 240 | status = errno2status(rc); 241 | goto End; 242 | } 243 | 244 | handle->maxMsgLen = me->buf_size; 245 | handle->protcolVer = me->prot_ver; 246 | 247 | status = TEE_SUCCESS; 248 | 249 | End: 250 | FUNC_EXIT(handle, status); 251 | return status; 252 | } 253 | 254 | TEESTATUS TEEAPI TeeRead(IN PTEEHANDLE handle, IN OUT void *buffer, IN size_t bufferSize, 255 | OUT OPTIONAL size_t *pNumOfBytesRead, IN OPTIONAL uint32_t timeout) 256 | { 257 | struct mei *me = to_mei(handle); 258 | struct metee_linux_intl *intl = to_intl(handle); 259 | int ltimeout; 260 | TEESTATUS status; 261 | ssize_t rc; 262 | 263 | if (!handle) { 264 | return TEE_INVALID_PARAMETER; 265 | } 266 | 267 | FUNC_ENTRY(handle); 268 | 269 | if (!me || !buffer || !bufferSize) { 270 | ERRPRINT(handle, "One of the parameters was illegal\n"); 271 | status = TEE_INVALID_PARAMETER; 272 | goto End; 273 | } 274 | 275 | if (timeout > INT_MAX) { 276 | ERRPRINT(handle, "Timeout is too big %u > %d \n", timeout, INT_MAX); 277 | status = TEE_INVALID_PARAMETER; 278 | goto End; 279 | } 280 | 281 | if (me->state != MEI_CL_STATE_CONNECTED) { 282 | ERRPRINT(handle, "The client is not connected\n"); 283 | status = TEE_DISCONNECTED; 284 | goto End; 285 | } 286 | 287 | DBGPRINT(handle, "call read length = %zd\n", bufferSize); 288 | 289 | ltimeout = (timeout) ? (int)timeout : -1; 290 | 291 | rc = __mei_select(me, intl->cancel_pipe[1], true, ltimeout); 292 | if (rc) { 293 | status = errno2status(rc); 294 | ERRPRINT(handle, "select failed with status %zd %s\n", 295 | rc, strerror(-rc)); 296 | goto End; 297 | } 298 | 299 | rc = mei_recv_msg(me, buffer, bufferSize); 300 | if (rc < 0) { 301 | status = errno2status(rc); 302 | ERRPRINT(handle, "read failed with status %zd %s\n", 303 | rc, strerror(-rc)); 304 | goto End; 305 | } 306 | 307 | status = TEE_SUCCESS; 308 | DBGPRINT(handle, "read succeeded with result %zd\n", rc); 309 | if (pNumOfBytesRead) 310 | *pNumOfBytesRead = (size_t)rc; 311 | 312 | End: 313 | FUNC_EXIT(handle, status); 314 | return status; 315 | } 316 | 317 | TEESTATUS TEEAPI TeeWrite(IN PTEEHANDLE handle, IN const void *buffer, IN size_t bufferSize, 318 | OUT OPTIONAL size_t *numberOfBytesWritten, IN OPTIONAL uint32_t timeout) 319 | { 320 | struct mei *me = to_mei(handle); 321 | struct metee_linux_intl *intl = to_intl(handle); 322 | int ltimeout; 323 | TEESTATUS status; 324 | ssize_t rc; 325 | 326 | if (!handle) { 327 | return TEE_INVALID_PARAMETER; 328 | } 329 | 330 | FUNC_ENTRY(handle); 331 | 332 | if (!me || !buffer || !bufferSize) { 333 | ERRPRINT(handle, "One of the parameters was illegal\n"); 334 | status = TEE_INVALID_PARAMETER; 335 | goto End; 336 | } 337 | 338 | if (timeout > INT_MAX) { 339 | ERRPRINT(handle, "Timeout is too big %u > %d \n", timeout, INT_MAX); 340 | status = TEE_INVALID_PARAMETER; 341 | goto End; 342 | } 343 | 344 | if (me->state != MEI_CL_STATE_CONNECTED) { 345 | ERRPRINT(handle, "The client is not connected\n"); 346 | status = TEE_DISCONNECTED; 347 | goto End; 348 | } 349 | 350 | DBGPRINT(handle, "call write length = %zd\n", bufferSize); 351 | 352 | ltimeout = (timeout) ? (int)timeout : -1; 353 | 354 | rc = __mei_select(me, intl->cancel_pipe[1], false, ltimeout); 355 | if (rc) { 356 | status = errno2status(rc); 357 | ERRPRINT(handle, "select failed with status %zd %s\n", 358 | rc, strerror(-rc)); 359 | goto End; 360 | } 361 | 362 | rc = mei_send_msg(me, buffer, bufferSize); 363 | if (rc < 0) { 364 | status = errno2status(rc); 365 | ERRPRINT(handle, "write failed with status %zd %s\n", rc, strerror(-rc)); 366 | goto End; 367 | } 368 | 369 | if (numberOfBytesWritten) 370 | *numberOfBytesWritten = (size_t)rc; 371 | 372 | status = TEE_SUCCESS; 373 | End: 374 | FUNC_EXIT(handle, status); 375 | return status; 376 | } 377 | 378 | TEESTATUS TEEAPI TeeFWStatus(IN PTEEHANDLE handle, 379 | IN uint32_t fwStatusNum, OUT uint32_t *fwStatus) 380 | { 381 | struct mei *me = to_mei(handle); 382 | TEESTATUS status; 383 | uint32_t fwsts; 384 | int rc; 385 | 386 | if (!handle) { 387 | return TEE_INVALID_PARAMETER; 388 | } 389 | 390 | FUNC_ENTRY(handle); 391 | 392 | if (!me || !fwStatus) { 393 | status = TEE_INVALID_PARAMETER; 394 | ERRPRINT(handle, "One of the parameters was illegal\n"); 395 | goto End; 396 | } 397 | if (fwStatusNum > MAX_FW_STATUS_NUM) { 398 | status = TEE_INVALID_PARAMETER; 399 | ERRPRINT(handle, "fwStatusNum should be 0..5\n"); 400 | goto End; 401 | } 402 | 403 | rc = mei_fwstatus(me, fwStatusNum, &fwsts); 404 | if (rc < 0) { 405 | status = errno2status(rc); 406 | ERRPRINT(handle, "fw status failed with status %d %s\n", rc, strerror(-rc)); 407 | goto End; 408 | } 409 | 410 | *fwStatus = fwsts; 411 | status = TEE_SUCCESS; 412 | 413 | End: 414 | FUNC_EXIT(handle, status); 415 | return status; 416 | } 417 | 418 | TEESTATUS TEEAPI TeeGetTRC(IN PTEEHANDLE handle, OUT uint32_t* trc_val) 419 | { 420 | struct mei* me = to_mei(handle); 421 | TEESTATUS status; 422 | uint32_t trc; 423 | int rc; 424 | 425 | if (!handle) { 426 | return TEE_INVALID_PARAMETER; 427 | } 428 | 429 | FUNC_ENTRY(handle); 430 | 431 | if (!me || !trc_val) { 432 | status = TEE_INVALID_PARAMETER; 433 | ERRPRINT(handle, "One of the parameters was illegal\n"); 434 | goto End; 435 | } 436 | 437 | rc = mei_gettrc(me, &trc); 438 | if (rc < 0) { 439 | status = errno2status(rc); 440 | ERRPRINT(handle, "TRC get failed with status %d %s\n", rc, strerror(-rc)); 441 | goto End; 442 | } 443 | 444 | *trc_val = trc; 445 | status = TEE_SUCCESS; 446 | 447 | End: 448 | FUNC_EXIT(handle, status); 449 | return status; 450 | } 451 | 452 | void TEEAPI TeeDisconnect(PTEEHANDLE handle) 453 | { 454 | struct metee_linux_intl *intl = to_intl(handle); 455 | const char buf[] = "X"; 456 | 457 | if (!handle) { 458 | return; 459 | } 460 | 461 | FUNC_ENTRY(handle); 462 | if (intl) { 463 | if (write(intl->cancel_pipe[1], buf, sizeof(buf)) < 0) { 464 | ERRPRINT(handle, "Pipe write failed\n"); 465 | } 466 | mei_deinit(&intl->me); 467 | close(intl->cancel_pipe[0]); 468 | close(intl->cancel_pipe[1]); 469 | free(intl); 470 | handle->handle = NULL; 471 | } 472 | 473 | FUNC_EXIT(handle, TEE_SUCCESS); 474 | } 475 | 476 | TEE_DEVICE_HANDLE TEEAPI TeeGetDeviceHandle(IN PTEEHANDLE handle) 477 | { 478 | struct mei *me = to_mei(handle); 479 | 480 | if (!handle) { 481 | return TEE_INVALID_PARAMETER; 482 | } 483 | 484 | if (!me) { 485 | DBGPRINT(handle, "Internal structure is not initialized\n"); 486 | return TEE_INVALID_DEVICE_HANDLE; 487 | } 488 | 489 | return me->fd; 490 | } 491 | 492 | TEESTATUS TEEAPI GetDriverVersion(IN PTEEHANDLE handle, IN OUT teeDriverVersion_t *driverVersion) 493 | { 494 | struct mei *me = to_mei(handle); 495 | TEESTATUS status; 496 | 497 | if (!handle) { 498 | return TEE_INVALID_PARAMETER; 499 | } 500 | 501 | FUNC_ENTRY(handle); 502 | 503 | if (!me || !driverVersion) { 504 | ERRPRINT(handle, "One of the parameters was illegal\n"); 505 | status = TEE_INVALID_PARAMETER; 506 | goto End; 507 | } 508 | 509 | status = TEE_NOTSUPPORTED; 510 | End: 511 | FUNC_EXIT(handle, status); 512 | return status; 513 | } 514 | 515 | uint32_t TEEAPI TeeSetLogLevel(IN PTEEHANDLE handle, IN uint32_t log_level) 516 | { 517 | struct mei *me = to_mei(handle); 518 | uint32_t prev_log_level = TEE_LOG_LEVEL_ERROR; 519 | 520 | if (!handle) { 521 | return prev_log_level; 522 | } 523 | 524 | FUNC_ENTRY(handle); 525 | 526 | if (!me) { 527 | ERRPRINT(handle, "Illegal handle\n"); 528 | goto End; 529 | } 530 | 531 | prev_log_level = handle->log_level; 532 | handle->log_level = (log_level > TEE_LOG_LEVEL_VERBOSE) ? TEE_LOG_LEVEL_VERBOSE : log_level; 533 | 534 | mei_set_log_level(me, handle->log_level); 535 | 536 | End: 537 | FUNC_EXIT(handle, prev_log_level); 538 | return prev_log_level; 539 | } 540 | 541 | uint32_t TEEAPI TeeGetLogLevel(IN const PTEEHANDLE handle) 542 | { 543 | uint32_t prev_log_level = TEE_LOG_LEVEL_ERROR; 544 | 545 | if (!handle) { 546 | return prev_log_level; 547 | } 548 | 549 | FUNC_ENTRY(handle); 550 | 551 | prev_log_level = handle->log_level; 552 | 553 | FUNC_EXIT(handle, prev_log_level); 554 | 555 | return prev_log_level; 556 | } 557 | 558 | TEESTATUS TEEAPI TeeSetLogCallback(IN const PTEEHANDLE handle, TeeLogCallback log_callback) 559 | { 560 | struct mei *me = to_mei(handle); 561 | TEESTATUS status; 562 | 563 | if (!handle) { 564 | return TEE_INVALID_PARAMETER; 565 | } 566 | 567 | FUNC_ENTRY(handle); 568 | 569 | if (!me) { 570 | status = TEE_INVALID_PARAMETER; 571 | ERRPRINT(handle, "One of the parameters was illegal\n"); 572 | goto Cleanup; 573 | } 574 | 575 | handle->log_callback = log_callback; 576 | mei_set_log_callback(me, log_callback); 577 | status = TEE_SUCCESS; 578 | 579 | Cleanup: 580 | FUNC_EXIT(handle, status); 581 | return status; 582 | } 583 | 584 | uint32_t TEEAPI TeeGetMaxMsgLen(IN const PTEEHANDLE handle) 585 | { 586 | if (!handle) { 587 | return 0; 588 | } 589 | return (uint32_t)handle->maxMsgLen; 590 | } 591 | 592 | uint8_t TEEAPI TeeGetProtocolVer(IN const PTEEHANDLE handle) 593 | { 594 | if (!handle) { 595 | return 0; 596 | } 597 | return handle->protcolVer; 598 | } 599 | 600 | TEESTATUS TEEAPI TeeGetKind(IN PTEEHANDLE handle, IN OUT char *kind, IN OUT size_t *kindSize) 601 | { 602 | struct mei* me = to_mei(handle); 603 | TEESTATUS status; 604 | int rc; 605 | 606 | if (!handle) { 607 | return TEE_INVALID_PARAMETER; 608 | } 609 | 610 | FUNC_ENTRY(handle); 611 | 612 | if (!me || !kindSize) { 613 | status = TEE_INVALID_PARAMETER; 614 | ERRPRINT(handle, "One of the parameters was illegal\n"); 615 | goto End; 616 | } 617 | 618 | rc = mei_getkind(me, kind, kindSize); 619 | if (rc < 0) { 620 | status = errno2status(rc); 621 | if (status == TEE_INSUFFICIENT_BUFFER) { 622 | DBGPRINT(handle, "Insufficient buffer %zu\n", *kindSize); 623 | } else { 624 | ERRPRINT(handle, "kind get failed with status %d %s\n", rc, strerror(-rc)); 625 | } 626 | goto End; 627 | } 628 | 629 | status = TEE_SUCCESS; 630 | 631 | End: 632 | FUNC_EXIT(handle, status); 633 | return status; 634 | } -------------------------------------------------------------------------------- /src/uefi/heci_core.h: -------------------------------------------------------------------------------- 1 | 2 | /* SPDX-License-Identifier: Apache-2.0 */ 3 | /* 4 | * Copyright (C) 2024 Intel Corporation 5 | */ 6 | #ifndef HECI_CORE_H_ 7 | #define HECI_CORE_H_ 8 | #include "metee.h" 9 | 10 | struct METEE_EFI_IMPL; 11 | 12 | #define NON_BLOCKING 0 13 | #define BLOCKING 1 14 | 15 | /** 16 | Function forces a reinit of the heci interface by following the reset heci interface via host algorithm 17 | in HPS section 4.1.1.1 18 | 19 | @param[in] Handle The HECI handle to be accessed. 20 | 21 | @retval EFI_SUCCESS Interface reset successful 22 | @retval EFI_TIMEOUT ME is not ready 23 | **/ 24 | EFI_STATUS 25 | EFIAPI 26 | ResetHeciInterface( 27 | IN struct METEE_EFI_IMPL *Handle); 28 | 29 | /** 30 | Function sends one message (of any length) through the HECI circular buffer. 31 | 32 | @param[in] Handle HECI handle to be accessed. 33 | @param[in] Message Pointer to the message data to be sent. 34 | @param[in] Length Length of the message in bytes. 35 | @param[in] HostAddress The address of the host processor. 36 | @param[in] MeAddress Address of the ME subsystem the message is being sent to. 37 | 38 | @retval EFI_SUCCESS One message packet sent. 39 | @retval EFI_DEVICE_ERROR Failed to initialize HECI 40 | @retval EFI_NOT_READY HECI is not ready for communication 41 | @retval EFI_TIMEOUT FW failed to empty the circular buffer 42 | @retval EFI_UNSUPPORTED Current ME mode doesn't support send this message through this HECI 43 | **/ 44 | EFI_STATUS 45 | EFIAPI 46 | HeciSend( 47 | IN struct METEE_EFI_IMPL *Handle, 48 | IN UINT32 *Message, 49 | IN UINT32 Length, 50 | IN UINT8 HostAddress, 51 | IN UINT8 MeAddress); 52 | 53 | /** 54 | Reads a message from FW through HECI. 55 | 56 | @param[in] Handle HECI handle to be accessed. 57 | @param[in] Blocking Used to determine if the read is BLOCKING or NON_BLOCKING. 58 | @param[in, out] MessageBody Pointer to a buffer used to receive a message. 59 | @param[in, out] Length Pointer to the length of the buffer on input and the length 60 | of the message on return. (in bytes) 61 | 62 | @retval EFI_SUCCESS One message packet read. 63 | @retval EFI_DEVICE_ERROR Failed to initialize HECI 64 | @retval EFI_NOT_READY HECI is not ready for communication 65 | @retval EFI_TIMEOUT Failed to receive a full message on time 66 | @retval EFI_NO_RESPONSE No response from FW 67 | @retval EFI_BUFFER_TOO_SMALL The caller's buffer was not large enough 68 | **/ 69 | EFI_STATUS 70 | EFIAPI 71 | HeciReceive( 72 | IN struct METEE_EFI_IMPL *Handle, 73 | IN UINT32 Blocking, 74 | IN OUT UINT32 *MessageBody, 75 | IN OUT UINT32 *Length); 76 | 77 | #endif // HECI_CORE_H_ -------------------------------------------------------------------------------- /src/uefi/heci_efi.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2024 Intel Corporation 4 | */ 5 | #ifndef HECI_EFI_H_ 6 | #define HECI_EFI_H_ 7 | 8 | #include "metee_efi.h" 9 | 10 | EFI_STATUS 11 | HeciConnectClient( 12 | IN struct METEE_EFI_IMPL *Handle); 13 | 14 | EFI_STATUS 15 | HeciReceiveMessage( 16 | IN struct METEE_EFI_IMPL *Handle, 17 | OUT UINT8 *Buffer, 18 | IN UINT32 BufferSize, 19 | OUT UINT32 *NumOfBytesRead, 20 | IN UINT32 timeout); 21 | 22 | EFI_STATUS 23 | HeciSendMessage( 24 | IN struct METEE_EFI_IMPL *Handle, 25 | IN const UINT8 *buffer, 26 | IN UINT32 bufferLength, 27 | OUT UINT32 *BytesWritten, 28 | IN UINT32 timeout); 29 | 30 | EFI_STATUS 31 | HeciFwStatus( 32 | IN struct METEE_EFI_IMPL *Handle, 33 | IN UINT32 fwStatusNum, 34 | OUT UINT32 *fwStatus); 35 | 36 | EFI_STATUS 37 | HeciGetTrc( 38 | IN struct METEE_EFI_IMPL *Handle, 39 | OUT UINT32 *trcVal); 40 | 41 | EFI_STATUS 42 | HeciUninitialize( 43 | IN struct METEE_EFI_IMPL *Handle); 44 | 45 | #endif // HECI_EFI_H_ -------------------------------------------------------------------------------- /src/uefi/metee_efi.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2024 Intel Corporation 4 | */ 5 | #ifndef METEE_EFI_H_ 6 | #define METEE_EFI_H_ 7 | 8 | 9 | enum METEE_CLIENT_STATE 10 | { 11 | METEE_CLIENT_STATE_NONE, 12 | METEE_CLIENT_STATE_CONNECTED, 13 | METEE_CLIENT_STATE_FAILED 14 | }; 15 | 16 | 17 | #define MAX_CONNECT_RETRIES 3 18 | #define HECI_FLOW_CTRL_MSG_LEN 8 19 | 20 | 21 | /** 22 | * HECI HW Section 23 | */ 24 | 25 | /** 26 | * HECI addresses and defines 27 | */ 28 | 29 | 30 | /** 31 | * register bits - H_CSR 32 | */ 33 | #define H_CBD 0xFF000000 /** Host Circular Buffer Depth */ 34 | #define H_CBWP 0x00FF0000 /** Host Circular Buffer Write Pointer */ 35 | #define H_CBRP 0x0000FF00 /** Host Circular Buffer Read Pointer */ 36 | #define H_RST 0x00000010 /** Host Reset */ 37 | #define H_RDY 0x00000008 /** Host Ready */ 38 | #define H_IG 0x00000004 /** Host Interrupt Generate */ 39 | #define H_IS 0x00000002 /** Host Interrupt Status */ 40 | #define H_IE 0x00000001 /** Host Interrupt Enable */ 41 | 42 | /** 43 | * register bits - ME_CSR_HA 44 | */ 45 | #define ME_CBD_HRA 0xFF000000 /** ME Circular Buffer Depth Host Read Access */ 46 | #define ME_CBWP_HRA 0x00FF0000 /** ME Circular Buffer Write Pointer Host Read Access */ 47 | #define ME_CBRP_HRA 0x0000FF00 /** ME Circular Buffer Read Pointer Host Read Access */ 48 | #define ME_RST_HRA 0x00000010 /** ME Reset Host Read Access */ 49 | #define ME_RDY_HRA 0x00000008 /** ME Ready Host Read Access */ 50 | #define ME_IG_HRA 0x00000004 /** ME Interrupt Generate Host Read Access */ 51 | #define ME_IS_HRA 0x00000002 /** ME Interrupt Status Host Read Access */ 52 | #define ME_IE_HRA 0x00000001 /** ME Interrupt Enable Host Read Access */ 53 | 54 | /** 55 | * HECI BUS Interface Section 56 | */ 57 | 58 | #define HOST_ENUM_REQ_CMD 0x04 59 | #define HOST_ENUM_RES_CMD 0x84 60 | 61 | #define HOST_CLIENT_PROPERTIES_REQ_CMD 0x05 62 | #define HOST_CLIENT_PROPERTIES_RES_CMD 0x85 63 | 64 | #define CLIENT_CONNECT_REQ_CMD 0x06 65 | #define CLIENT_CONNECT_RES_CMD 0x86 66 | 67 | #define CLIENT_DISCONNECT_REQ_CMD 0x07 68 | #define CLIENT_DISCONNECT_RES_CMD 0x87 69 | 70 | #define FLOW_CONTROL_CMD 0x08 71 | 72 | #pragma pack(1) 73 | 74 | typedef struct _HBM_HOST_ENUMERATION_REQUEST 75 | { 76 | UINT8 Command; 77 | UINT8 ClientReqBits; 78 | UINT8 Reserved[2]; 79 | } HBM_HOST_ENUMERATION_REQUEST; 80 | 81 | typedef struct _HBM_HOST_ENUMERATION_RESPONSE 82 | { 83 | UINT8 Command; 84 | UINT8 Reserved[3]; 85 | UINT8 ValidAddresses[32]; 86 | } HBM_HOST_ENUMERATION_RESPONSE; 87 | 88 | typedef struct _HBM_CLIENT_CONNECT_REQUEST 89 | { 90 | UINT8 Command; 91 | UINT8 MEAddress; 92 | UINT8 HostAddress; 93 | UINT8 Reserved; 94 | } HBM_CLIENT_CONNECT_REQUEST; 95 | 96 | typedef struct _HBM_CLIENT_CONNECT_RESPONSE 97 | { 98 | UINT8 Command; 99 | UINT8 MEAddress; 100 | UINT8 HostAddress; 101 | UINT8 Status; 102 | } HBM_CLIENT_CONNECT_RESPONSE; 103 | 104 | typedef struct _HBM_CLIENT_DISCONNECT_REQUEST 105 | { 106 | UINT8 Command; 107 | UINT8 MEAddress; 108 | UINT8 HostAddress; 109 | UINT8 Reserved[1]; 110 | } HBM_CLIENT_DISCONNECT_REQUEST; 111 | 112 | typedef struct _HBM_CLIENT_DISCONNECT_RESPONSE 113 | { 114 | UINT8 Command; 115 | UINT8 MEAddress; 116 | UINT8 HostAddress; 117 | UINT8 Status; 118 | UINT32 Pad; 119 | } HBM_CLIENT_DISCONNECT_RESPONSE; 120 | 121 | typedef enum _CLIENT_CONNECT_STATUS 122 | { 123 | CCS_SUCCESS = 0x00, 124 | CCS_ALREADY_STARTED = 0x02, 125 | } CLIENT_CONNECT_STATUS; 126 | 127 | typedef struct _HBM_FLOW_CONTROL 128 | { 129 | UINT8 Command; 130 | UINT8 MEAddress; 131 | UINT8 HostAddress; 132 | UINT8 Reserved[5]; 133 | } HBM_FLOW_CONTROL; 134 | 135 | typedef struct _HECI_CLIENT_PROPERTIES 136 | { 137 | GUID ProtocolName; 138 | UINT8 ProtocolVersion; 139 | UINT8 MaxNumberOfConnections; 140 | UINT8 Address; 141 | UINT8 SingleReceiveBuffer; 142 | UINT32 MaxMessageLength; 143 | UINT8 FixedAddress; 144 | } HECI_CLIENT_PROPERTIES; 145 | 146 | typedef struct _HECI_CLIENT_CONNECTION 147 | { 148 | HECI_CLIENT_PROPERTIES properties; 149 | UINT32 ResetGeneration; /** Should match device Link Reset */ 150 | UINT32 handle; 151 | BOOLEAN connected; 152 | UINT8 HostClientId; 153 | } HECI_CLIENT_CONNECTION; 154 | 155 | #pragma pack() 156 | 157 | 158 | #define HECI_FW_STS_COUNT 6 159 | 160 | struct HECI_HW_BDF { 161 | UINT32 Segment; /** HECI device Segment */ 162 | UINT32 Bus; /** HECI device Bus */ 163 | UINT32 Device; /** HECI device Device */ 164 | UINT32 Function; /** HECI device Function */ 165 | }; 166 | 167 | struct HECI_HW { 168 | struct HECI_HW_BDF Bdf; 169 | struct RegisterOffset { 170 | UINT32 H_CB_WW; /** Host Circular Buffer Write Window */ 171 | UINT32 H_CSR; /** Host Control Status */ 172 | UINT32 ME_CB_RW; /** ME Circular Buffer Read Window */ 173 | UINT32 ME_CSR_HA; /** ME Control Status Host Access */ 174 | UINT32 BaseAddressOffset; /** HECI registers offset inside device MMIO */ 175 | } RegisterOffset; 176 | struct FwStatus { 177 | UINT32 FW_STS[HECI_FW_STS_COUNT]; /** FW status registers offsets */ 178 | BOOLEAN ResidesInConfigSpace; /** FW status resides in config space or MMIO */ 179 | } FwStatus; 180 | UINT32 TrcOffset; /** TRC register offset */ 181 | }; 182 | 183 | struct _TEEHANDLE; 184 | struct METEE_EFI_IMPL 185 | { 186 | struct _TEEHANDLE *TeeHandle; 187 | GUID ClientGuid; /** Client GUID */ 188 | enum METEE_CLIENT_STATE State; /** The client state */ 189 | HECI_CLIENT_CONNECTION HeciClientConnection; /** HECI EFI Connection information */ 190 | struct HECI_HW Hw; /** HECI HW information */ 191 | enum HECI_HW_TYPE HwType; /** HECI HW type */ 192 | }; 193 | 194 | #define HECI_EFI_PRINT_BDF_STR "[HECI %d:%d:%d:%d] " 195 | #define HECI_EFI_PRINT_BDF_VAL Handle->Hw.Bdf.Segment, Handle->Hw.Bdf.Bus, Handle->Hw.Bdf.Device, Handle->Hw.Bdf.Function 196 | 197 | #define EFIPRINT(Handle, fmt, ...) DBGPRINT(Handle, HECI_EFI_PRINT_BDF_STR fmt, HECI_EFI_PRINT_BDF_VAL, ##__VA_ARGS__); 198 | 199 | #endif // METEE_EFI_H_ 200 | -------------------------------------------------------------------------------- /src/uefi/pci_utils.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2024 Intel Corporation 4 | */ 5 | 6 | #include <Uefi.h> 7 | #include <Library/BaseLib.h> 8 | #include <Library/UefiLib.h> 9 | #include <Library/PciSegmentLib.h> 10 | #include <IndustryStandard/Pci22.h> 11 | 12 | #include "metee.h" 13 | #include "metee_efi.h" 14 | #include "heci_efi.h" 15 | 16 | #include "helpers.h" 17 | 18 | 19 | /** 20 | Get HECI controller address that can be passed to the PCI Segment Library functions. 21 | 22 | @param[in] Handle The HECI Handle to be accessed. 23 | 24 | @retval HECI controller address in PCI Segment Library representation 25 | **/ 26 | UINT64 27 | HeciPciCfgBase( 28 | IN struct METEE_EFI_IMPL *Handle) 29 | { 30 | return PCI_SEGMENT_LIB_ADDRESS( 31 | Handle->Hw.Bdf.Segment, 32 | Handle->Hw.Bdf.Bus, 33 | Handle->Hw.Bdf.Device, 34 | Handle->Hw.Bdf.Function, 35 | 0); 36 | } 37 | 38 | /** 39 | This function provides a standard way to verify the HECI cmd and MBAR regs 40 | in its PCI cfg space are setup properly. 41 | 42 | @param[in] Handle The HECI Handle to be accessed. 43 | 44 | @retval HeciMemBar HECI Memory BAR. 45 | 0 - invalid BAR value returned. 46 | **/ 47 | UINT64 48 | CheckAndFixHeciForAccess( 49 | IN struct METEE_EFI_IMPL *Handle) 50 | { 51 | UINT64 HeciBaseAddress; 52 | UINT64 MemBar; 53 | UINT32 LowPart; 54 | UINT64 HiPart; 55 | 56 | #define B_PCI_BAR_MEMORY_TYPE_64 0x4 57 | 58 | HeciBaseAddress = HeciPciCfgBase(Handle); 59 | if (HeciBaseAddress == 0) 60 | { 61 | EFIPRINT(Handle->TeeHandle, "HeciPciCfgBase is 0\n"); 62 | return 0; 63 | } 64 | EFIPRINT(Handle->TeeHandle, "HeciBaseAddress 0x%p\n", HeciBaseAddress); 65 | /// 66 | /// Check for HECI PCI device availability 67 | /// 68 | if (PciSegmentRead16(HeciBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) 69 | { 70 | EFIPRINT(Handle->TeeHandle, "is not enabled in this phase\n"); 71 | return 0; 72 | } 73 | LowPart = PciSegmentRead32(HeciBaseAddress + PCI_BASE_ADDRESSREG_OFFSET); 74 | HiPart = (UINT64)PciSegmentRead32(HeciBaseAddress + (PCI_BASE_ADDRESSREG_OFFSET + 4)); 75 | MemBar = LowPart & 0xFFFFFFF0; 76 | 77 | if ((LowPart & B_PCI_BAR_MEMORY_TYPE_64) == B_PCI_BAR_MEMORY_TYPE_64) 78 | { 79 | MemBar += LShiftU64(HiPart, 32); 80 | } 81 | 82 | if (MemBar == 0) 83 | { 84 | EFIPRINT(Handle->TeeHandle, "MMIO Bar for isn't programmed in this phase\n"); 85 | return 0; 86 | } 87 | /// 88 | /// Enable HECI MSE 89 | /// 90 | PciSegmentOr8(HeciBaseAddress + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE); 91 | 92 | return MemBar + Handle->Hw.RegisterOffset.BaseAddressOffset; 93 | } 94 | -------------------------------------------------------------------------------- /src/uefi/pci_utils.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2024 Intel Corporation 4 | */ 5 | #ifndef HECI_PCI_UTILS_H_ 6 | #define HECI_PCI_UTILS_H_ 7 | 8 | struct METEE_EFI_IMPL; 9 | 10 | #include <Uefi.h> 11 | 12 | /** 13 | Get HECI controller address that can be passed to the PCI Segment Library functions. 14 | 15 | @param[in] Handle The HECI Handle to be accessed. 16 | 17 | @retval HECI controller address in PCI Segment Library representation 18 | **/ 19 | UINT64 20 | HeciPciCfgBase( 21 | IN struct METEE_EFI_IMPL *Handle); 22 | 23 | /** 24 | This function provides a standard way to verify the HECI cmd and MBAR regs 25 | in its PCI cfg space are setup properly. 26 | 27 | @param[in] Handle The HECI Handle to be accessed. 28 | 29 | @retval HeciMemBar HECI Memory BAR. 30 | 0 - invalid BAR value returned. 31 | **/ 32 | UINT64 33 | CheckAndFixHeciForAccess( 34 | IN struct METEE_EFI_IMPL *Handle); 35 | 36 | #endif // HECI_PCI_UTILS_H_ -------------------------------------------------------------------------------- /tests/AMTHI.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2014-2019 Intel Corporation 4 | */ 5 | #ifndef __AMTHI_H 6 | #define __AMTHI_H 7 | 8 | #include <windows.h> 9 | 10 | static const UINT32 BIOS_VERSION_LEN = 65; 11 | static const UINT32 VERSIONS_NUMBER = 50; 12 | static const UINT32 UNICODE_STRING_LEN = 20; 13 | 14 | typedef unsigned int PT_STATUS; 15 | typedef unsigned int AMT_STATUS; 16 | 17 | 18 | #pragma pack(1) 19 | typedef struct _AMT_UNICODE_STRING 20 | { 21 | UINT16 Length; 22 | UINT8 String[UNICODE_STRING_LEN]; 23 | } AMT_UNICODE_STRING; 24 | 25 | typedef struct _AMT_VERSION_TYPE 26 | { 27 | AMT_UNICODE_STRING Description; 28 | AMT_UNICODE_STRING Version; 29 | }AMT_VERSION_TYPE; 30 | 31 | typedef struct _PTHI_VERSION 32 | { 33 | UINT8 MajorNumber; 34 | UINT8 MinorNumber; 35 | } PTHI_VERSION; 36 | 37 | typedef struct _CODE_VERSIONS 38 | { 39 | UINT8 BiosVersion[BIOS_VERSION_LEN]; 40 | UINT32 VersionsCount; 41 | AMT_VERSION_TYPE Versions[VERSIONS_NUMBER]; 42 | } CODE_VERSIONS; 43 | 44 | typedef struct _COMMAND_FMT 45 | { 46 | union 47 | { 48 | UINT32 val; 49 | struct 50 | { 51 | UINT32 Operation : 23; 52 | UINT32 IsResponse : 1; 53 | UINT32 Class : 8; 54 | } fields; 55 | } cmd; 56 | 57 | } COMMAND_FMT; 58 | 59 | typedef struct _AMT_ANSI_STRING 60 | { 61 | UINT16 Length; 62 | CHAR* Buffer; 63 | }AMT_ANSI_STRING; 64 | 65 | 66 | typedef struct _PTHI_MESSAGE_HEADER 67 | { 68 | PTHI_VERSION Version; 69 | UINT16 Reserved; 70 | COMMAND_FMT Command; 71 | UINT32 Length; 72 | 73 | } PTHI_MESSAGE_HEADER; 74 | 75 | typedef struct _CFG_GET_CODE_VERSIONS_RESPONSE 76 | { 77 | PTHI_MESSAGE_HEADER Header; 78 | AMT_STATUS Status; 79 | CODE_VERSIONS CodeVersions; 80 | } CFG_GET_CODE_VERSIONS_RESPONSE; 81 | 82 | const UINT32 CODE_VERSIONS_REQUEST = 0x0400001A; 83 | const UINT32 CODE_VERSIONS_RESPONSE = 0x0480001A; 84 | 85 | const PTHI_MESSAGE_HEADER GET_CODE_VERSION_HEADER = 86 | { 87 | {1,1},0,{CODE_VERSIONS_REQUEST},0 88 | }; 89 | 90 | 91 | 92 | typedef struct 93 | { 94 | UINT8 Command; 95 | UINT8 ByteCount; 96 | UINT8 SubCommand; 97 | UINT8 VersionNumber; 98 | } AMT_GetMngMacAddress_Request; 99 | 100 | typedef struct 101 | { 102 | UINT8 Command; 103 | UINT8 ByteCount; 104 | UINT8 SubCommand; 105 | UINT8 VersionNumber; 106 | AMT_STATUS Status; 107 | UINT8 Address[6]; // returned upon success only 108 | } AMT_GetMngMacAddress_Response; 109 | #pragma pack() 110 | 111 | #endif -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright (C) 2014-2025 Intel Corporation 3 | cmake_minimum_required(VERSION 3.15) 4 | project(metee_test) 5 | 6 | set(CMAKE_CXX_STANDARD 11) 7 | 8 | if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/googletest-src) 9 | file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/googletest-src 10 | DESTINATION ${CMAKE_CURRENT_BINARY_DIR} 11 | ) 12 | else(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/googletest-src) 13 | # Download and unpack googletest at configure time 14 | configure_file(gtest.cmake.in googletest-download/CMakeLists.txt) 15 | execute_process( 16 | COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . 17 | RESULT_VARIABLE result 18 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download 19 | ) 20 | if(result) 21 | message(FATAL_ERROR "CMake step for googletest failed: ${result}") 22 | endif() 23 | execute_process( 24 | COMMAND ${CMAKE_COMMAND} --build . 25 | RESULT_VARIABLE result 26 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download 27 | ) 28 | if(result) 29 | message(FATAL_ERROR "Build step for googletest failed: ${result}") 30 | endif() 31 | endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/googletest-src) 32 | 33 | # Prevent overriding the parent project's compiler/linker settings on Windows 34 | set(gtest_force_shared_crt 35 | ON 36 | CACHE BOOL "" FORCE 37 | ) 38 | 39 | # Add googletest directly to our build. This defines the gtest and gtest_main 40 | # targets. 41 | add_subdirectory( 42 | ${CMAKE_CURRENT_BINARY_DIR}/googletest-src 43 | ${CMAKE_CURRENT_BINARY_DIR}/googletest-build EXCLUDE_FROM_ALL 44 | ) 45 | 46 | add_executable(${PROJECT_NAME} 47 | Main.cpp 48 | metee_test.cpp 49 | meteepp_test.cpp 50 | $<$<BOOL:${WIN32}>:${CMAKE_SOURCE_DIR}/src/Windows/metee_winhelpers.c> 51 | ) 52 | if(NOT CONSOLE_OUTPUT) 53 | target_compile_definitions(${PROJECT_NAME} PRIVATE -DSYSLOG) 54 | endif() 55 | 56 | target_link_libraries(${PROJECT_NAME} metee gtest_main gmock_main) 57 | 58 | target_include_directories(${PROJECT_NAME} 59 | PRIVATE ${CMAKE_SOURCE_DIR}/src/Windows 60 | ) 61 | 62 | install(TARGETS ${PROJECT_NAME} 63 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 64 | ) 65 | 66 | -------------------------------------------------------------------------------- /tests/MKHI.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2014-2019 Intel Corporation 4 | */ 5 | #pragma pack(1) 6 | #define GEN_GET_MKHI_VERSION_CMD 0x01 7 | #define GEN_GET_FW_VERSION_CMD 0x02 8 | 9 | // Typedef for GroupID 10 | typedef enum 11 | { 12 | MKHI_CBM_GROUP_ID = 0, 13 | MKHI_PM_GROUP_ID, 14 | MKHI_PWD_GROUP_ID, 15 | MKHI_FWCAPS_GROUP_ID, 16 | MKHI_APP_GROUP_ID, // Reserved (no longer used). 17 | MKHI_FWUPDATE_GROUP_ID, // This is for manufacturing downgrade 18 | MKHI_FIRMWARE_UPDATE_GROUP_ID, 19 | MKHI_BIST_GROUP_ID, 20 | MKHI_MDES_GROUP_ID, 21 | MKHI_ME_DBG_GROUP_ID, 22 | MKHI_MAX_GROUP_ID, 23 | MKHI_GEN_GROUP_ID = 0xFF 24 | }MKHI_GROUP_ID; 25 | //MKHI host message header. This header is part of HECI message sent from MEBx via 26 | //Host Configuration Interface (HCI). ME Configuration Manager or Power Configuration 27 | //Manager also include this header with appropriate fields set as part of the 28 | //response message to the HCI. 29 | typedef union _MKHI_MESSAGE_HEADER 30 | { 31 | uint32_t Data; 32 | struct 33 | { 34 | uint32_t GroupId : 8; 35 | uint32_t Command : 7; 36 | uint32_t IsResponse : 1; 37 | uint32_t Reserved : 8; 38 | uint32_t Result : 8; 39 | }Fields; 40 | }MKHI_MESSAGE_HEADER; 41 | static_assert(sizeof(MKHI_MESSAGE_HEADER) == 4, "MKHI header should be 4 bytes exactly!"); 42 | 43 | typedef struct _GEN_GET_FW_VERSION 44 | { 45 | MKHI_MESSAGE_HEADER Header; 46 | }GEN_GET_FW_VERSION; 47 | 48 | typedef struct _FW_VERSION 49 | { 50 | uint32_t CodeMinor : 16; 51 | uint32_t CodeMajor : 16; 52 | uint32_t CodeBuildNo : 16; 53 | uint32_t CodeHotFix : 16; 54 | uint32_t NFTPMinor : 16; 55 | uint32_t NFTPMajor : 16; 56 | uint32_t NFTPBuildNo : 16; 57 | uint32_t NFTPHotFix : 16; 58 | }FW_VERSION; 59 | 60 | typedef struct _GET_FW_VERSION_ACK_DATA 61 | { 62 | FW_VERSION FWVersion; 63 | }GET_FW_VERSION_ACK_DATA; 64 | 65 | typedef struct _GEN_GET_FW_VERSION_ACK 66 | { 67 | MKHI_MESSAGE_HEADER Header; 68 | GET_FW_VERSION_ACK_DATA Data; 69 | }GEN_GET_FW_VERSION_ACK; 70 | DEFINE_GUID(GUID_DEVINTERFACE_MKHI, 0x8e6a6715, 0x9abc, 0x4043, 71 | 0x88, 0xef, 0x9e, 0x39, 0xc6, 0xf6, 0x3e, 0x0f); 72 | #pragma pack() -------------------------------------------------------------------------------- /tests/Main.cpp: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2014-2019 Intel Corporation 4 | */ 5 | #include "metee_test.h" 6 | 7 | int main(int argc, char* argv[]) 8 | { 9 | ::testing::InitGoogleTest(&argc, argv); 10 | 11 | return RUN_ALL_TESTS(); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /tests/gtest.cmake.in: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright (C) 2014-2022 Intel Corporation 3 | cmake_minimum_required(VERSION 3.1) 4 | 5 | project(googletest-download NONE) 6 | 7 | include(ExternalProject) 8 | ExternalProject_Add(googletest 9 | GIT_REPOSITORY https://github.com/google/googletest.git 10 | GIT_TAG release-1.12.1 11 | SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" 12 | BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" 13 | CONFIGURE_COMMAND "" 14 | BUILD_COMMAND "" 15 | INSTALL_COMMAND "" 16 | TEST_COMMAND "" 17 | ) 18 | -------------------------------------------------------------------------------- /tests/metee_test.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2014-2025 Intel Corporation 4 | */ 5 | #include <memory.h> 6 | #include <string> 7 | #include <fstream> 8 | #include <chrono> 9 | #include <thread> 10 | #include <vector> 11 | #include <climits> 12 | #include "gtest/gtest.h" 13 | #include <gmock/gmock.h> 14 | 15 | #include "metee.h" 16 | #include "meteepp.h" 17 | #include "helpers.h" 18 | #ifdef WIN32 19 | #include <windows.h> 20 | #else 21 | #define ERROR_INVALID_HANDLE -ENOTTY 22 | #define ERROR_NOT_FOUND -ENODEV 23 | #define INVALID_HANDLE_VALUE ((void*)0) 24 | #include <sys/resource.h> 25 | #endif // WIN32 26 | #include "MKHI.h" 27 | 28 | std::string GetErrorString(unsigned long LastError); 29 | 30 | TEESTATUS ConnectRetry(PTEEHANDLE handle); 31 | 32 | //Print Expected and Ectual in Hex. 33 | namespace testing { 34 | namespace internal { 35 | inline void PrintTo(unsigned long n, ::std::ostream* os) { 36 | (*os) << "0x" << std::hex << n << " " << (GetErrorString(n)); 37 | } 38 | } 39 | } 40 | 41 | #ifdef _WIN32 42 | inline TEESTATUS TestTeeInitGUID(PTEEHANDLE handle, const GUID *guid, const GUID *device) 43 | { 44 | if (device != NULL) 45 | return TeeInitGUID(handle, guid, device); 46 | else 47 | return TeeInit(handle, guid, NULL); 48 | } 49 | #else /* _WIN32 */ 50 | inline TEESTATUS TestTeeInitGUID(PTEEHANDLE handle, const GUID *guid, const GUID *device) 51 | { 52 | return TeeInit(handle, guid, NULL); 53 | } 54 | #endif /* _WIN32 */ 55 | 56 | struct MeTeeTESTParams { 57 | const char *name; 58 | const GUID *device; 59 | const GUID *client; 60 | }; 61 | 62 | class MeTeeTEST : public ::testing::TestWithParam<struct MeTeeTESTParams>{ 63 | public: 64 | MeTeeTEST() { 65 | // initialization code here 66 | } 67 | 68 | void SetUp() { 69 | #ifdef _DEBUG 70 | printf("Enter ProdTests SetUp\n"); 71 | #endif 72 | MkhiRequest.Header.Fields.Command = GEN_GET_FW_VERSION_CMD; 73 | MkhiRequest.Header.Fields.GroupId = MKHI_GEN_GROUP_ID; 74 | MkhiRequest.Header.Fields.IsResponse = 0; 75 | #ifdef _DEBUG 76 | printf("Exit ProdTests SetUp\n"); 77 | #endif 78 | } 79 | 80 | void TearDown() { 81 | #ifdef _DEBUG 82 | printf("Enter ProdTests TearDown\n"); 83 | #endif 84 | 85 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); //Is it helping? 86 | #ifdef _DEBUG 87 | printf("Exit ProdTests TearDown\n"); 88 | #endif 89 | } 90 | 91 | ~MeTeeTEST() { 92 | // cleanup any pending stuff, but no exceptions allowed 93 | } 94 | GEN_GET_FW_VERSION MkhiRequest; 95 | }; 96 | 97 | class MeTeePPTEST : public ::testing::TestWithParam<struct MeTeeTESTParams> { 98 | public: 99 | MeTeePPTEST() { 100 | // initialization code here 101 | } 102 | 103 | void SetUp() { 104 | GEN_GET_FW_VERSION req; 105 | #ifdef _DEBUG 106 | printf("Enter ProdTests SetUp\n"); 107 | #endif 108 | req.Header.Fields.Command = GEN_GET_FW_VERSION_CMD; 109 | req.Header.Fields.GroupId = MKHI_GEN_GROUP_ID; 110 | req.Header.Fields.IsResponse = 0; 111 | auto ptr = reinterpret_cast<uint8_t*>(&req); 112 | MkhiRequest = std::vector<uint8_t>(ptr, ptr + sizeof(GEN_GET_FW_VERSION)); 113 | #ifdef _DEBUG 114 | printf("Exit ProdTests SetUp\n"); 115 | #endif 116 | } 117 | 118 | void TearDown() { 119 | #ifdef _DEBUG 120 | printf("Enter ProdTests TearDown\n"); 121 | #endif 122 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 123 | #ifdef _DEBUG 124 | printf("Exit ProdTests TearDown\n"); 125 | #endif 126 | } 127 | 128 | ~MeTeePPTEST() { 129 | // cleanup any pending stuff, but no exceptions allowed 130 | } 131 | std::vector<uint8_t> MkhiRequest; 132 | }; 133 | 134 | class MeTeeFDTEST : public ::testing::TestWithParam<struct MeTeeTESTParams> { 135 | public: 136 | MeTeeFDTEST() : deviceHandle(TEE_INVALID_DEVICE_HANDLE) { 137 | // initialization code here 138 | } 139 | 140 | void SetUp() { 141 | OpenMEI(); 142 | if (deviceHandle == TEE_INVALID_DEVICE_HANDLE) 143 | GTEST_SKIP(); 144 | MkhiRequest.Header.Fields.Command = GEN_GET_FW_VERSION_CMD; 145 | MkhiRequest.Header.Fields.GroupId = MKHI_GEN_GROUP_ID; 146 | MkhiRequest.Header.Fields.IsResponse = 0; 147 | } 148 | 149 | void TearDown() { 150 | CloseMEI(); 151 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); //Is it helping? 152 | } 153 | 154 | ~MeTeeFDTEST() { 155 | // cleanup any pending stuff, but no exceptions allowed 156 | } 157 | GEN_GET_FW_VERSION MkhiRequest; 158 | private: 159 | void OpenMEI(); 160 | void CloseMEI(); 161 | public: 162 | TEE_DEVICE_HANDLE deviceHandle; 163 | }; 164 | 165 | class MeTeeOpenTEST : public ::testing::TestWithParam<struct MeTeeTESTParams> { 166 | public: 167 | MeTeeOpenTEST() { 168 | // initialization code here 169 | __tee_init_handle(&_handle); 170 | } 171 | 172 | void SetUp() { 173 | struct MeTeeTESTParams intf = GetParam(); 174 | TEESTATUS status; 175 | 176 | _handle.handle = NULL; 177 | 178 | status = TestTeeInitGUID(&_handle, intf.client, intf.device); 179 | if (status == TEE_DEVICE_NOT_FOUND) 180 | GTEST_SKIP(); 181 | ASSERT_EQ(TEE_SUCCESS, status); 182 | ASSERT_NE(TEE_INVALID_DEVICE_HANDLE, TeeGetDeviceHandle(&_handle)); 183 | MkhiRequest.Header.Fields.Command = GEN_GET_FW_VERSION_CMD; 184 | MkhiRequest.Header.Fields.GroupId = MKHI_GEN_GROUP_ID; 185 | MkhiRequest.Header.Fields.IsResponse = 0; 186 | } 187 | 188 | void TearDown() { 189 | TeeDisconnect(&_handle); 190 | //Is this helping? 191 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 192 | } 193 | 194 | ~MeTeeOpenTEST() { 195 | // cleanup any pending stuff, but no exceptions allowed 196 | } 197 | TEEHANDLE _handle; 198 | GEN_GET_FW_VERSION MkhiRequest; 199 | }; 200 | 201 | class MeTeeDataNTEST : public ::testing::TestWithParam<struct MeTeeTESTParams> { 202 | public: 203 | MeTeeDataNTEST() { 204 | // initialization code here 205 | __tee_init_handle(&_handle); 206 | } 207 | 208 | void SetUp() { 209 | struct MeTeeTESTParams intf = GetParam(); 210 | TEESTATUS status; 211 | 212 | #ifdef _DEBUG 213 | printf("Enter ProdTests SetUp\n"); 214 | #endif 215 | _handle.handle = NULL; 216 | 217 | status = TestTeeInitGUID(&_handle, intf.client, intf.device); 218 | if (status == TEE_DEVICE_NOT_FOUND) 219 | GTEST_SKIP(); 220 | ASSERT_EQ(TEE_SUCCESS, status); 221 | ASSERT_NE(TEE_INVALID_DEVICE_HANDLE, TeeGetDeviceHandle(&_handle)); 222 | ASSERT_EQ(TEE_SUCCESS, ConnectRetry(&_handle)); 223 | MkhiRequest.Header.Fields.Command = GEN_GET_FW_VERSION_CMD; 224 | MkhiRequest.Header.Fields.GroupId = MKHI_GEN_GROUP_ID; 225 | MkhiRequest.Header.Fields.IsResponse = 0; 226 | #ifdef _DEBUG 227 | printf("Exit ProdTests SetUp\n"); 228 | #endif 229 | } 230 | 231 | void TearDown() { 232 | #ifdef _DEBUG 233 | printf("Enter ProdTests TearDown\n"); 234 | #endif 235 | TeeDisconnect(&_handle); 236 | //Is this helping? 237 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 238 | #ifdef _DEBUG 239 | printf("Exit ProdTests TearDown\n"); 240 | #endif 241 | } 242 | 243 | ~MeTeeDataNTEST() { 244 | // cleanup any pending stuff, but no exceptions allowed 245 | } 246 | TEEHANDLE _handle; 247 | GEN_GET_FW_VERSION MkhiRequest; 248 | }; 249 | 250 | class MeTee1000OpenTEST : public ::testing::TestWithParam<struct MeTeeTESTParams>{ 251 | public: 252 | MeTee1000OpenTEST() { 253 | // initialization code here 254 | } 255 | 256 | void SetUp() { 257 | #ifdef _DEBUG 258 | printf("Enter MeTee1000OpenTEST SetUp\n"); 259 | #endif 260 | MkhiRequest.Header.Fields.Command = GEN_GET_FW_VERSION_CMD; 261 | MkhiRequest.Header.Fields.GroupId = MKHI_GEN_GROUP_ID; 262 | MkhiRequest.Header.Fields.IsResponse = 0; 263 | 264 | #ifdef __linux__ 265 | struct rlimit limit; 266 | 267 | limit.rlim_cur = 2048; 268 | limit.rlim_max = 2048; 269 | errno = 0; 270 | if (setrlimit(RLIMIT_NOFILE, &limit) != 0) 271 | FAIL() << "setrlimit() failed with errno=" << errno; 272 | #endif // __linux__ 273 | 274 | for (int g = 0; g <= 199; g++) { 275 | v.push_back(std::thread([g]() { 276 | int base = g * 10; 277 | int i = 0; 278 | std::ofstream file0; 279 | std::string name0 = "example_" + std::to_string(base) + ".txt"; 280 | std::ofstream file1; 281 | std::string name1 = "example_" + std::to_string(base + 1) + ".txt"; 282 | std::ofstream file2; 283 | std::string name2 = "example_" + std::to_string(base + 2) + ".txt"; 284 | std::ofstream file3; 285 | std::string name3 = "example_" + std::to_string(base + 3) + ".txt"; 286 | std::ofstream file4; 287 | std::string name4 = "example_" + std::to_string(base + 4) + ".txt"; 288 | std::ofstream file5; 289 | std::string name5 = "example_" + std::to_string(base + 5) + ".txt"; 290 | std::ofstream file6; 291 | std::string name6 = "example_" + std::to_string(base + 6) + ".txt"; 292 | std::ofstream file7; 293 | std::string name7 = "example_" + std::to_string(base + 7) + ".txt"; 294 | std::ofstream file8; 295 | std::string name8 = "example_" + std::to_string(base + 8) + ".txt"; 296 | std::ofstream file9; 297 | std::string name9 = "example_" + std::to_string(base + 9) + ".txt"; 298 | file0.open(name0); 299 | file1.open(name1); 300 | file2.open(name2); 301 | file3.open(name3); 302 | file4.open(name4); 303 | file5.open(name5); 304 | file6.open(name6); 305 | file7.open(name7); 306 | file8.open(name8); 307 | file9.open(name9); 308 | while (i++ < 5) { 309 | file0 << "Writing to " << name0 << std::endl; 310 | file1 << "Writing to " << name1 << std::endl; 311 | file2 << "Writing to " << name2 << std::endl; 312 | file3 << "Writing to " << name3 << std::endl; 313 | file4 << "Writing to " << name4 << std::endl; 314 | file5 << "Writing to " << name5 << std::endl; 315 | file6 << "Writing to " << name6 << std::endl; 316 | file7 << "Writing to " << name7 << std::endl; 317 | file8 << "Writing to " << name8 << std::endl; 318 | file9 << "Writing to " << name9 << std::endl; 319 | std::this_thread::sleep_for(std::chrono::seconds(5)); 320 | } 321 | file0.close(); 322 | file1.close(); 323 | file2.close(); 324 | file3.close(); 325 | file4.close(); 326 | file5.close(); 327 | file6.close(); 328 | file7.close(); 329 | file8.close(); 330 | file9.close(); 331 | remove(name0.c_str()); 332 | remove(name1.c_str()); 333 | remove(name2.c_str()); 334 | remove(name3.c_str()); 335 | remove(name4.c_str()); 336 | remove(name5.c_str()); 337 | remove(name6.c_str()); 338 | remove(name7.c_str()); 339 | remove(name8.c_str()); 340 | remove(name9.c_str()); 341 | })); 342 | } 343 | std::this_thread::sleep_for(std::chrono::seconds(5)); 344 | #ifdef _DEBUG 345 | printf("Exit MeTee1000OpenTEST SetUp\n"); 346 | #endif 347 | } 348 | 349 | void TearDown() { 350 | #ifdef _DEBUG 351 | printf("Enter MeTee1000OpenTEST TearDown\n"); 352 | #endif 353 | 354 | for (std::vector<std::thread>::iterator it = v.begin(); it != v.end(); it++) 355 | it->std::thread::join(); 356 | 357 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); //Is it helping? 358 | #ifdef _DEBUG 359 | printf("Exit MeTee1000OpenTEST TearDown\n"); 360 | #endif 361 | } 362 | 363 | ~MeTee1000OpenTEST() { 364 | // cleanup any pending stuff, but no exceptions allowed 365 | } 366 | GEN_GET_FW_VERSION MkhiRequest; 367 | std::vector<std::thread> v; 368 | }; 369 | -------------------------------------------------------------------------------- /tests/meteepp_test.cpp: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: Apache-2.0 */ 2 | /* 3 | * Copyright (C) 2021-2025 Intel Corporation 4 | */ 5 | #include "metee_test.h" 6 | 7 | DEFINE_GUID(GUID_NON_EXISTS_CLIENT, 8 | 0x85eb8fa6, 0xbdd, 0x4d01, 0xbe, 0xc4, 0xa5, 0x97, 0x43, 0x4e, 0xd7, 0x62); 9 | 10 | TEST_P(MeTeePPTEST, PROD_MKHI_SimpleGetVersion) 11 | { 12 | struct MeTeeTESTParams intf = GetParam(); 13 | std::vector<uint8_t> MaxResponse; 14 | GEN_GET_FW_VERSION_ACK* pResponseMessage; 15 | 16 | for (int i = 1; i < 2; i++) { 17 | try { 18 | intel::security::metee metee(*intf.client); 19 | 20 | ASSERT_NE(TEE_INVALID_DEVICE_HANDLE, metee.device_handle()); 21 | metee.connect(); 22 | 23 | ASSERT_EQ(MkhiRequest.size(), metee.write(MkhiRequest, 0)); 24 | 25 | MaxResponse = metee.read(0); 26 | ASSERT_LE(sizeof(GEN_GET_FW_VERSION_ACK), MaxResponse.size()); 27 | pResponseMessage = reinterpret_cast<GEN_GET_FW_VERSION_ACK*>(MaxResponse.data()); 28 | 29 | ASSERT_EQ(TEE_SUCCESS, pResponseMessage->Header.Fields.Result); 30 | EXPECT_NE(0, pResponseMessage->Data.FWVersion.CodeMajor); 31 | EXPECT_NE(0, pResponseMessage->Data.FWVersion.CodeBuildNo); 32 | } 33 | catch(const intel::security::metee_exception &ex){ 34 | if (ex.code().value() == TEE_DEVICE_NOT_FOUND) 35 | GTEST_SKIP(); 36 | FAIL() << "Excepton: " << ex.what(); 37 | } 38 | } 39 | } 40 | 41 | TEST_P(MeTeePPTEST, PROD_N_Kind) 42 | { 43 | struct MeTeeTESTParams intf = GetParam(); 44 | 45 | try { 46 | intel::security::metee metee(*intf.client); 47 | 48 | ASSERT_NE(TEE_INVALID_DEVICE_HANDLE, metee.device_handle()); 49 | 50 | ASSERT_GE(metee.kind().length(), 0); 51 | } 52 | catch (const intel::security::metee_exception& ex) { 53 | if (ex.code().value() == TEE_DEVICE_NOT_FOUND) 54 | GTEST_SKIP(); 55 | if (ex.code().value() != TEE_NOTSUPPORTED) 56 | FAIL() << "Excepton: " << ex.what(); 57 | } 58 | } 59 | 60 | TEST_P(MeTeePPTEST, PROD_MKHI_InitFull) 61 | { 62 | struct MeTeeTESTParams intf = GetParam(); 63 | std::vector<uint8_t> MaxResponse; 64 | GEN_GET_FW_VERSION_ACK* pResponseMessage; 65 | 66 | try { 67 | struct tee_device_address device = {tee_device_address::TEE_DEVICE_TYPE_NONE, { NULL }}; 68 | 69 | intel::security::metee metee(*intf.client, device, TEE_LOG_LEVEL_VERBOSE, NULL); 70 | 71 | ASSERT_NE(TEE_INVALID_DEVICE_HANDLE, metee.device_handle()); 72 | metee.connect(); 73 | } 74 | catch (const intel::security::metee_exception& ex) { 75 | if (ex.code().value() == TEE_DEVICE_NOT_FOUND) 76 | GTEST_SKIP(); 77 | FAIL() << "Excepton: " << ex.what(); 78 | } 79 | } 80 | 81 | TEST_P(MeTeePPTEST, PROD_N_TestConnectToNonExistsUuid) 82 | { 83 | struct MeTeeTESTParams intf = GetParam(); 84 | 85 | try { 86 | intel::security::metee metee(GUID_NON_EXISTS_CLIENT); 87 | ASSERT_NE(TEE_INVALID_DEVICE_HANDLE, metee.device_handle()); 88 | metee.connect(); 89 | } 90 | catch (const intel::security::metee_exception& ex) { 91 | if (ex.code().value() == TEE_DEVICE_NOT_FOUND) 92 | GTEST_SKIP(); 93 | if (ex.code().value() == TEE_CLIENT_NOT_FOUND) 94 | return; 95 | FAIL() << "Excepton: " << ex.what(); 96 | } 97 | FAIL(); 98 | } 99 | 100 | TEST_P(MeTeePPTEST, PROD_MKHI_MoveSemantics) 101 | { 102 | struct MeTeeTESTParams intf = GetParam(); 103 | std::vector<uint8_t> MaxResponse; 104 | GEN_GET_FW_VERSION_ACK* pResponseMessage; 105 | 106 | intel::security::metee metee2; 107 | 108 | try { 109 | intel::security::metee metee(*intf.client); 110 | ASSERT_NE(TEE_INVALID_DEVICE_HANDLE, metee.device_handle()); 111 | metee.connect(); 112 | 113 | metee2 = std::move(metee); 114 | } 115 | catch (const intel::security::metee_exception& ex) { 116 | if (ex.code().value() == TEE_DEVICE_NOT_FOUND) 117 | GTEST_SKIP(); 118 | FAIL() << "Excepton: " << ex.what(); 119 | } 120 | 121 | ASSERT_EQ(MkhiRequest.size(), metee2.write(MkhiRequest, 0)); 122 | 123 | MaxResponse = metee2.read(0); 124 | ASSERT_LE(sizeof(GEN_GET_FW_VERSION_ACK), MaxResponse.size()); 125 | pResponseMessage = reinterpret_cast<GEN_GET_FW_VERSION_ACK*>(MaxResponse.data()); 126 | 127 | ASSERT_EQ(TEE_SUCCESS, pResponseMessage->Header.Fields.Result); 128 | EXPECT_NE(0, pResponseMessage->Data.FWVersion.CodeMajor); 129 | EXPECT_NE(0, pResponseMessage->Data.FWVersion.CodeBuildNo); 130 | } 131 | 132 | static struct MeTeeTESTParams interfaces[1] = { 133 | {"PCH", NULL, &GUID_DEVINTERFACE_MKHI}}; 134 | 135 | INSTANTIATE_TEST_SUITE_P(MeTeePPTESTInstance, MeTeePPTEST, 136 | testing::ValuesIn(interfaces), 137 | [](const testing::TestParamInfo<MeTeePPTEST::ParamType>& info) { 138 | return info.param.name; 139 | }); -------------------------------------------------------------------------------- /version.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright (C) 2014-2024 Intel Corporation 3 | 4 | file(READ VERSION VER_FILE) 5 | string(STRIP "${VER_FILE}" VER_FILE) 6 | string(REPLACE "." ";" VER_LIST ${VER_FILE}) 7 | list(GET VER_LIST 0 TEE_VERSION_MAJOR) 8 | list(GET VER_LIST 1 TEE_VERSION_MINOR) 9 | list(GET VER_LIST 2 TEE_VERSION_PATCH) 10 | set(TEE_VERSION_STRING 11 | ${TEE_VERSION_MAJOR}.${TEE_VERSION_MINOR}.${TEE_VERSION_PATCH}) 12 | set(TEE_VERSION_COMM 13 | ${TEE_VERSION_MAJOR},${TEE_VERSION_MINOR},${TEE_VERSION_PATCH},0) -------------------------------------------------------------------------------- /win32.cmake: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright (C) 2014-2024 Intel Corporation 3 | 4 | if(BUILD_MSVC_RUNTIME_STATIC) 5 | set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") 6 | endif() 7 | 8 | set(TEE_SOURCES 9 | src/Windows/metee_win.c 10 | src/Windows/metee_winhelpers.c 11 | ${PROJECT_BINARY_DIR}/metee.rc 12 | ) 13 | 14 | add_library(${PROJECT_NAME} ${TEE_SOURCES}) 15 | 16 | target_link_libraries(${PROJECT_NAME} CfgMgr32.lib) 17 | target_compile_definitions(${PROJECT_NAME} PRIVATE 18 | UNICODE _UNICODE 19 | $<$<BOOL:BUILD_SHARED_LIBS>:METEE_DLL> 20 | $<$<BOOL:BUILD_SHARED_LIBS>:METEE_DLL_EXPORT> 21 | ) 22 | if(NOT CONSOLE_OUTPUT) 23 | target_compile_definitions(${PROJECT_NAME} PRIVATE -DSYSLOG) 24 | endif() 25 | 26 | configure_file ( 27 | "${PROJECT_SOURCE_DIR}/src/Windows/metee.rc.in" 28 | "${PROJECT_BINARY_DIR}/metee.rc" 29 | ) 30 | 31 | # Secure compile flags 32 | target_compile_options(${PROJECT_NAME} 33 | PRIVATE /GS /sdl) 34 | 35 | # More warnings and warning-as-error 36 | target_compile_options(${PROJECT_NAME} 37 | PRIVATE /W4 /WX 38 | ) 39 | 40 | set_target_properties(${PROJECT_NAME} 41 | PROPERTIES COMPILE_FLAGS "/Zi" 42 | ) 43 | 44 | set_target_properties(${PROJECT_NAME} 45 | PROPERTIES PDB_NAME "${PROJECT_NAME}" 46 | PDB_NAME_DEBUG "${PROJECT_NAME}" 47 | COMPILE_PDB_NAME "${PROJECT_NAME}" 48 | COMPILE_PDB_NAME_DEBUG "${PROJECT_NAME}" 49 | ) 50 | 51 | if(${BUILD_SHARED_LIBS}) 52 | install(FILES $<TARGET_PDB_FILE:${PROJECT_NAME}> DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL) 53 | else() 54 | install(FILES "$<TARGET_FILE_DIR:${PROJECT_NAME}>/${PROJECT_NAME}.pdb" DESTINATION ${CMAKE_INSTALL_LIBDIR} OPTIONAL) 55 | endif() --------------------------------------------------------------------------------