Compare commits
277 Commits
edk2-stabl
...
edk2-stabl
Author | SHA1 | Date | |
---|---|---|---|
8736b8fdca | |||
f444c4bea5 | |||
8dd52c949e | |||
15538bc62e | |||
23dbb8a07d | |||
3db76e6476 | |||
06b27ccb90 | |||
c9cce5a005 | |||
33deaa3b84 | |||
706811819d | |||
05f3c3f3d0 | |||
1cb580be85 | |||
431ead235f | |||
589f2e49e5 | |||
35c0c63edb | |||
e077ccff6d | |||
8a41004643 | |||
212cf07aaa | |||
68e37f4578 | |||
616f0d5037 | |||
bb18fb80ab | |||
c96b4da2a0 | |||
d461137e22 | |||
a3e8efcc8e | |||
1384ce443d | |||
29763016e0 | |||
b531ca4bb3 | |||
5464d0bed6 | |||
c1393bd486 | |||
da21991953 | |||
e53c618ea4 | |||
ae02d487a3 | |||
778134e491 | |||
ee942c5360 | |||
038499a268 | |||
08ac799d36 | |||
0b4acb88d6 | |||
8da978bf68 | |||
fbbbd98499 | |||
1b1509abee | |||
ccbe2e9383 | |||
36812d6c3e | |||
a6871b5359 | |||
2e128302e6 | |||
fe6cd1c187 | |||
d4358a7f76 | |||
f3b2187d55 | |||
8e74629070 | |||
2426a35625 | |||
aa8431822b | |||
a671a14e63 | |||
08431081a3 | |||
09fd4e4172 | |||
3ee23713e1 | |||
f81ee47513 | |||
4821daa524 | |||
2b0d117b4b | |||
50e8518276 | |||
36e9f3d08a | |||
cf62548a35 | |||
db9800dce8 | |||
f9925c8953 | |||
822c54eb01 | |||
4f3ee7fbaf | |||
7806713f00 | |||
7f5c24ad35 | |||
7ff6ab2b3e | |||
7e08d17a4a | |||
ca32f75fc6 | |||
1e27258a89 | |||
a00f7a355a | |||
716a3292e0 | |||
504953ef97 | |||
41c622523d | |||
d0cac9f63f | |||
f945b72331 | |||
601abf5d50 | |||
ba5d955e25 | |||
b7e6d97973 | |||
115b59d9c6 | |||
66046aeb6d | |||
5fc3c39704 | |||
f078a6fdd4 | |||
eb83b53309 | |||
74c687cc2f | |||
fe43b42676 | |||
9a38ddc806 | |||
8765f3eb42 | |||
1cbdd6e9ff | |||
cf68ff6130 | |||
9bb5ef1287 | |||
884ef98454 | |||
00dbde5fa4 | |||
1f21e11168 | |||
cf87fd95c1 | |||
170d4ce8e9 | |||
d85bf54b7f | |||
a6648418c1 | |||
e17e58e81b | |||
fb044b7fe8 | |||
da73578bf7 | |||
2ad52adb66 | |||
87ef986eeb | |||
f8923b72de | |||
e44097a965 | |||
e5b4fe21ae | |||
b24c8b0467 | |||
1cd0227c5d | |||
22b667c821 | |||
2298769ecf | |||
36b41b067f | |||
cbcdf4ff7b | |||
9f5e409623 | |||
309450db26 | |||
ec7f734366 | |||
575bd4f55c | |||
c591395f4a | |||
bed477d9cf | |||
0355e559c6 | |||
96ed60dfd7 | |||
8abbf6d87e | |||
b75d9f556d | |||
7fe49887c4 | |||
3c3136d3b6 | |||
e6e0e7ba74 | |||
189addfde6 | |||
c62fb45549 | |||
747a08eae2 | |||
01e1bc2894 | |||
772ec92577 | |||
a445e1a42c | |||
03d6569f70 | |||
e07948255c | |||
326b9e1d81 | |||
eebd446875 | |||
c109e4a244 | |||
26754b3707 | |||
c5fedb030a | |||
4049ca493c | |||
b26f7dfe29 | |||
97f51f2e9b | |||
60222e7eb9 | |||
731aa70881 | |||
586f05b9de | |||
1a79cc7d95 | |||
95c9f470ca | |||
137f799aae | |||
01b0d19dbb | |||
c4fdec0a83 | |||
4b7b32f846 | |||
c032db3308 | |||
1d0fd0bb3d | |||
1217f59d23 | |||
cc070b88e4 | |||
0103d09ebe | |||
a519014472 | |||
0d89ceae31 | |||
5b76b4a9f9 | |||
1ec374cb50 | |||
f784fc0e39 | |||
ca3f8638fa | |||
bf03c4a52a | |||
4ddd8ac3a2 | |||
5087a07736 | |||
82191f8a0e | |||
6439c73356 | |||
d073a54511 | |||
1497c4b074 | |||
1a66bd51ca | |||
2b2705343a | |||
ae79efb7bd | |||
80bbea192a | |||
cbf0e4f5b3 | |||
f6a314e5b5 | |||
f36e1ec1f0 | |||
ad1c0394b1 | |||
be971fc302 | |||
bf0bdacdd6 | |||
39f3c26e8c | |||
d6b05375b4 | |||
c70d914428 | |||
d11f0ea045 | |||
43dcf453fc | |||
8b2e6b90b8 | |||
909e870e34 | |||
b5003ab725 | |||
fd0ccccb42 | |||
b2df3ee17f | |||
8f5505a4c9 | |||
28a267af40 | |||
e9f5d8c0e0 | |||
f67e1934d9 | |||
ea628f28e5 | |||
89dad77cfb | |||
4317b4824b | |||
4fb69c2bee | |||
eb485b6438 | |||
baee97670f | |||
7275993dc6 | |||
cbcf0428e8 | |||
97d367f37e | |||
8803033c0c | |||
1312c2e9fd | |||
bc7bbd3bc4 | |||
5cfb5d6c01 | |||
6f0729484f | |||
408e463135 | |||
db38c7de64 | |||
dea6002d6e | |||
718cf21a5a | |||
392456240a | |||
29cce3356a | |||
1bfd63ac39 | |||
5242bae5dd | |||
cdfe4310dd | |||
4a1afea6f7 | |||
b844b106e2 | |||
7f1a8cad99 | |||
6d074d6a10 | |||
c95158e419 | |||
4f4a2c3b07 | |||
b7a48bed16 | |||
e880c307c5 | |||
a5cbb59905 | |||
cc26a2cb31 | |||
f18ec60fa4 | |||
0bcc503595 | |||
b240eab035 | |||
d4ae5df711 | |||
d42ad81e22 | |||
28a74d7ab2 | |||
493a375eef | |||
60d0f5802b | |||
b74f1f7ab5 | |||
ff7ddc02b2 | |||
19438cff97 | |||
5443c2dc31 | |||
414c0f2089 | |||
cf07238e5f | |||
bd1f0eecc1 | |||
65b5dd828e | |||
e93468442b | |||
2f981bddcb | |||
2ce5ae43c2 | |||
cf82c09bac | |||
48de494bb4 | |||
bc19f50c70 | |||
b1955cddb2 | |||
634192665e | |||
b29150aa3e | |||
aff67922c5 | |||
163083fd80 | |||
b81557a00c | |||
bbf1822295 | |||
24da5c2f28 | |||
4d196352f3 | |||
9b3d4f28f0 | |||
d1e4a16f86 | |||
f008890ae5 | |||
a23f4377c1 | |||
8b66f9df1b | |||
dfb941d32a | |||
beafabdae4 | |||
4c8144dd66 | |||
a60eef3afa | |||
c5753c3e38 | |||
0c4d0b6c8a | |||
e8aa4c6546 | |||
a481c11144 | |||
5f46eb2307 | |||
9896a9c618 | |||
14bf2cb411 | |||
020cc9e2e7 | |||
a107fcb618 | |||
b1e558f636 | |||
2c7fd32676 | |||
92006e5804 |
@ -27,7 +27,7 @@ steps:
|
||||
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: '>=3.10.6'
|
||||
versionSpec: '3.12'
|
||||
architecture: 'x64'
|
||||
|
||||
- script: |
|
||||
|
@ -8,5 +8,5 @@
|
||||
##
|
||||
|
||||
variables:
|
||||
default_python_version: ">=3.10.6"
|
||||
default_python_version: "3.12"
|
||||
default_linux_image: "ghcr.io/tianocore/containers/fedora-37-test:a0dd931"
|
||||
|
31
.editorconfig
Normal file
31
.editorconfig
Normal file
@ -0,0 +1,31 @@
|
||||
# EditorConfig file: https://EditorConfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = latin1
|
||||
end_of_line = crlf
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.py]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.sh]
|
||||
end_of_line = lf
|
||||
|
||||
[.gitattributes]
|
||||
end_of_line = lf
|
||||
|
||||
[.mailmap]
|
||||
charset = utf-8
|
||||
|
||||
[Maintainers.txt]
|
||||
charset = utf-8
|
||||
|
||||
[Makefile,GNUmakefile]
|
||||
indent_style = tab
|
29
.github/codeql/codeql-config.yml
vendored
29
.github/codeql/codeql-config.yml
vendored
@ -1,29 +0,0 @@
|
||||
## @file
|
||||
# CodeQL configuration file for edk2.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
name: "CodeQL config"
|
||||
|
||||
# The following line disables the default queries. This is used because we want to enable on query at a time by
|
||||
# explicitly specifying each query in a "queries" array as they are enabled.
|
||||
#
|
||||
# See the following for more information about adding custom queries:
|
||||
# https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-a-custom-configuration-file
|
||||
|
||||
#disable-default-queries: true
|
||||
|
||||
queries:
|
||||
- name: EDK2 CodeQL Query List
|
||||
uses: ./.github/codeql/edk2.qls
|
||||
|
||||
# We must specify a query for CodeQL to run. Until the first query is enabled, enable the security query suite but
|
||||
# exclude all problem levels from impacting the results. After the first query is enabled, this filter can be relaxed
|
||||
# to find the level of problems desired from the query.
|
||||
query-filters:
|
||||
- exclude:
|
||||
problem.severity:
|
||||
- warning
|
||||
- recommendation
|
24
.github/codeql/edk2.qls
vendored
24
.github/codeql/edk2.qls
vendored
@ -1,24 +0,0 @@
|
||||
---
|
||||
- description: EDK2 (C++) queries
|
||||
|
||||
# Bring in all queries from the official cpp-queries suite so individual queries can be explicitly enabled.
|
||||
|
||||
- queries: '.'
|
||||
from: codeql/cpp-queries
|
||||
|
||||
# Enable individual queries below.
|
||||
|
||||
- include:
|
||||
id: cpp/conditionallyuninitializedvariable
|
||||
- include:
|
||||
id: cpp/infinite-loop-with-unsatisfiable-exit-condition
|
||||
- include:
|
||||
id: cpp/overflow-buffer
|
||||
- include:
|
||||
id: cpp/overrunning-write
|
||||
- include:
|
||||
id: cpp/overrunning-write-with-float
|
||||
- include:
|
||||
id: cpp/pointer-overflow-check
|
||||
- include:
|
||||
id: cpp/very-likely-overrunning-write
|
118
.github/workflows/codeql-analysis.yml
vendored
118
.github/workflows/codeql-analysis.yml
vendored
@ -1,118 +0,0 @@
|
||||
# @file
|
||||
# GitHub Workflow for CodeQL Analysis
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- '**/*.bat'
|
||||
- '**/*.md'
|
||||
- '**/*.py'
|
||||
- '**/*.rst'
|
||||
- '**/*.sh'
|
||||
- '**/*.txt'
|
||||
|
||||
schedule:
|
||||
# https://crontab.guru/#20_23_*_*_4
|
||||
- cron: '20 23 * * 4'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: windows-2019
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- Package: "ArmPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "CryptoPkg"
|
||||
ArchList: "IA32"
|
||||
- Package: "CryptoPkg"
|
||||
ArchList: "X64"
|
||||
- Package: "DynamicTablesPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "FatPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "FmpDevicePkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "IntelFsp2Pkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "IntelFsp2WrapperPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "MdeModulePkg"
|
||||
ArchList: "IA32"
|
||||
- Package: "MdeModulePkg"
|
||||
ArchList: "X64"
|
||||
- Package: "MdePkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "PcAtChipsetPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "PrmPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "SecurityPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "ShellPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "SourceLevelDebugPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "StandaloneMmPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "UefiCpuPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "UnitTestFrameworkPkg"
|
||||
ArchList: "IA32,X64"
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10.6'
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'pip-requirements.txt'
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: 'cpp'
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://codeql.github.com/docs/codeql-overview/supported-languages-and-frameworks/
|
||||
config-file: ./.github/codeql/codeql-config.yml
|
||||
# Note: Add new queries to codeql-config.yml file as they are enabled.
|
||||
|
||||
- name: Install/Upgrade pip Modules
|
||||
run: pip install -r pip-requirements.txt --upgrade
|
||||
|
||||
- name: Setup
|
||||
run: stuart_setup -c .pytool/CISettings.py -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019
|
||||
|
||||
- name: Update
|
||||
run: stuart_update -c .pytool/CISettings.py -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019
|
||||
|
||||
- name: Build Tools From Source
|
||||
run: python BaseTools/Edk2ToolsBuild.py -t VS2019
|
||||
|
||||
- name: CI Build
|
||||
run: stuart_ci_build -c .pytool/CISettings.py -p ${{ matrix.Package }} -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
338
.github/workflows/codeql.yml
vendored
Normal file
338
.github/workflows/codeql.yml
vendored
Normal file
@ -0,0 +1,338 @@
|
||||
# This workflow runs CodeQL against the repository.
|
||||
#
|
||||
# Results are uploaded to GitHub Code Scanning.
|
||||
#
|
||||
# Due to a known issue with the CodeQL extractor when building the edk2
|
||||
# codebase on Linux systems, only Windows agents are used for build with
|
||||
# the VS toolchain.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- '!**.c'
|
||||
- '!**.h'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: windows-2019
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- Package: "ArmPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "CryptoPkg"
|
||||
ArchList: "IA32"
|
||||
- Package: "CryptoPkg"
|
||||
ArchList: "X64"
|
||||
- Package: "DynamicTablesPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "FatPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "FmpDevicePkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "IntelFsp2Pkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "IntelFsp2WrapperPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "MdeModulePkg"
|
||||
ArchList: "IA32"
|
||||
- Package: "MdeModulePkg"
|
||||
ArchList: "X64"
|
||||
- Package: "MdePkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "PcAtChipsetPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "PrmPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "SecurityPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "ShellPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "SourceLevelDebugPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "StandaloneMmPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "UefiCpuPkg"
|
||||
ArchList: "IA32,X64"
|
||||
- Package: "UnitTestFrameworkPkg"
|
||||
ArchList: "IA32,X64"
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'pip-requirements.txt'
|
||||
|
||||
- name: Use Git Long Paths on Windows
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
git config --system core.longpaths true
|
||||
|
||||
- name: Install/Upgrade pip Modules
|
||||
run: pip install -r pip-requirements.txt --upgrade requests
|
||||
|
||||
- name: Determine CI Settings File Supported Operations
|
||||
id: get_ci_file_operations
|
||||
shell: python
|
||||
run: |
|
||||
import importlib
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from edk2toolext.invocables.edk2_ci_setup import CiSetupSettingsManager
|
||||
from edk2toolext.invocables.edk2_setup import SetupSettingsManager
|
||||
|
||||
# Find the repo CI Settings file
|
||||
ci_settings_file = list(Path(os.environ['GITHUB_WORKSPACE']).rglob('.pytool/CISettings.py'))
|
||||
|
||||
# Note: At this point, submodules have not been pulled, only one CI Settings file should exist
|
||||
if len(ci_settings_file) != 1 or not ci_settings_file[0].is_file():
|
||||
print("::error title=Workspace Error!::Failed to find CI Settings file!")
|
||||
sys.exit(1)
|
||||
|
||||
ci_settings_file = ci_settings_file[0]
|
||||
|
||||
# Try Finding the Settings class in the file
|
||||
module_name = 'ci_settings'
|
||||
|
||||
spec = importlib.util.spec_from_file_location(module_name, ci_settings_file)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
try:
|
||||
settings = getattr(module, 'Settings')
|
||||
except AttributeError:
|
||||
print("::error title=Workspace Error!::Failed to find Settings class in CI Settings file!")
|
||||
sys.exit(1)
|
||||
|
||||
# Determine Which Operations Are Supported by the Settings Class
|
||||
ci_setup_supported = issubclass(settings, CiSetupSettingsManager)
|
||||
setup_supported = issubclass(settings, SetupSettingsManager)
|
||||
|
||||
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
|
||||
print(f'ci_setup_supported={str(ci_setup_supported).lower()}', file=fh)
|
||||
print(f'setup_supported={str(setup_supported).lower()}', file=fh)
|
||||
|
||||
- name: Setup
|
||||
if: steps.get_ci_file_operations.outputs.setup_supported == 'true'
|
||||
run: stuart_setup -c .pytool/CISettings.py -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019
|
||||
|
||||
- name: Upload Setup Log As An Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
if: (success() || failure()) && steps.get_ci_file_operations.outputs.setup_supported == 'true'
|
||||
with:
|
||||
name: ${{ matrix.Package }}-Logs
|
||||
path: |
|
||||
**/SETUPLOG.txt
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: CI Setup
|
||||
if: steps.get_ci_file_operations.outputs.ci_setup_supported == 'true'
|
||||
run: stuart_ci_setup -c .pytool/CISettings.py -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019
|
||||
|
||||
- name: Upload CI Setup Log As An Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
if: (success() || failure()) && steps.get_ci_file_operations.outputs.ci_setup_supported == 'true'
|
||||
with:
|
||||
name: ${{ matrix.Package }}-Logs
|
||||
path: |
|
||||
**/CISETUP.txt
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Update
|
||||
run: stuart_update -c .pytool/CISettings.py -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019
|
||||
|
||||
- name: Upload Update Log As An Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
if: success() || failure()
|
||||
with:
|
||||
name: ${{ matrix.Package }}-Logs
|
||||
path: |
|
||||
**/UPDATE_LOG.txt
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Build Tools From Source
|
||||
run: python BaseTools/Edk2ToolsBuild.py -t VS2019
|
||||
|
||||
- name: Find CodeQL Plugin Directory
|
||||
id: find_dir
|
||||
shell: python
|
||||
run: |
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Find the plugin directory that contains the CodeQL plugin
|
||||
plugin_dir = list(Path(os.environ['GITHUB_WORKSPACE']).rglob('BaseTools/Plugin/CodeQL'))
|
||||
|
||||
# This should only be found once
|
||||
if len(plugin_dir) == 1:
|
||||
plugin_dir = str(plugin_dir[0])
|
||||
|
||||
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
|
||||
print(f'codeql_plugin_dir={plugin_dir}', file=fh)
|
||||
else:
|
||||
print("::error title=Workspace Error!::Failed to find CodeQL plugin directory!")
|
||||
sys.exit(1)
|
||||
|
||||
- name: Get CodeQL CLI Cache Data
|
||||
id: cache_key_gen
|
||||
env:
|
||||
CODEQL_PLUGIN_DIR: ${{ steps.find_dir.outputs.codeql_plugin_dir }}
|
||||
shell: python
|
||||
run: |
|
||||
import os
|
||||
import yaml
|
||||
|
||||
codeql_cli_ext_dep_name = 'codeqlcli_windows_ext_dep'
|
||||
codeql_plugin_file = os.path.join(os.environ['CODEQL_PLUGIN_DIR'], codeql_cli_ext_dep_name + '.yaml')
|
||||
|
||||
with open (codeql_plugin_file) as pf:
|
||||
codeql_cli_ext_dep = yaml.safe_load(pf)
|
||||
|
||||
cache_key_name = codeql_cli_ext_dep['name']
|
||||
cache_key_version = codeql_cli_ext_dep['version']
|
||||
cache_key = f'{cache_key_name}-{cache_key_version}'
|
||||
|
||||
codeql_plugin_cli_ext_dep_dir = os.path.join(os.environ['CODEQL_PLUGIN_DIR'], codeql_cli_ext_dep['name'].strip() + '_extdep')
|
||||
|
||||
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
|
||||
print(f'codeql_cli_cache_key={cache_key}', file=fh)
|
||||
print(f'codeql_cli_ext_dep_dir={codeql_plugin_cli_ext_dep_dir}', file=fh)
|
||||
|
||||
- name: Attempt to Load CodeQL CLI From Cache
|
||||
id: codeqlcli_cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.cache_key_gen.outputs.codeql_cli_ext_dep_dir }}
|
||||
key: ${{ steps.cache_key_gen.outputs.codeql_cli_cache_key }}
|
||||
|
||||
- name: Download CodeQL CLI
|
||||
if: steps.codeqlcli_cache.outputs.cache-hit != 'true'
|
||||
run: stuart_update -c .pytool/CISettings.py -t DEBUG -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019 --codeql
|
||||
|
||||
- name: Remove CI Plugins Irrelevant to CodeQL
|
||||
shell: python
|
||||
env:
|
||||
CODEQL_PLUGIN_DIR: ${{ steps.find_dir.outputs.codeql_plugin_dir }}
|
||||
run: |
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
# Only these two plugins are needed for CodeQL
|
||||
plugins_to_keep = ['CompilerPlugin']
|
||||
|
||||
plugin_dir = Path('.pytool/Plugin').absolute()
|
||||
if plugin_dir.is_dir():
|
||||
for dir in plugin_dir.iterdir():
|
||||
if str(dir.stem) not in plugins_to_keep:
|
||||
shutil.rmtree(str(dir.absolute()), ignore_errors=True)
|
||||
|
||||
- name: CI Build
|
||||
env:
|
||||
STUART_CODEQL_PATH: ${{ steps.cache_key_gen.outputs.codeql_cli_ext_dep_dir }}
|
||||
run: stuart_ci_build -c .pytool/CISettings.py -t DEBUG -p ${{ matrix.Package }} -a ${{ matrix.ArchList }} TOOL_CHAIN_TAG=VS2019 --codeql
|
||||
|
||||
- name: Build Cleanup
|
||||
id: build_cleanup
|
||||
shell: python
|
||||
run: |
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
dirs_to_delete = ['ia32', 'x64', 'arm', 'aarch64']
|
||||
|
||||
def delete_dirs(path: Path):
|
||||
if path.exists() and path.is_dir():
|
||||
if path.name.lower() in dirs_to_delete:
|
||||
print(f'Removed {str(path)}')
|
||||
shutil.rmtree(path)
|
||||
return
|
||||
|
||||
for child_dir in path.iterdir():
|
||||
delete_dirs(child_dir)
|
||||
|
||||
build_path = Path(os.environ['GITHUB_WORKSPACE'], 'Build')
|
||||
delete_dirs(build_path)
|
||||
|
||||
- name: Upload Build Logs As An Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
if: success() || failure()
|
||||
with:
|
||||
name: ${{ matrix.Package }}-Logs
|
||||
path: |
|
||||
**/BUILD_REPORT.TXT
|
||||
**/OVERRIDELOG.TXT
|
||||
**/BUILDLOG_*.md
|
||||
**/BUILDLOG_*.txt
|
||||
**/CI_*.md
|
||||
**/CI_*.txt
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Prepare Env Data for CodeQL Upload
|
||||
id: env_data
|
||||
env:
|
||||
PACKAGE_NAME: ${{ matrix.Package }}
|
||||
shell: python
|
||||
run: |
|
||||
import os
|
||||
|
||||
package = os.environ['PACKAGE_NAME'].strip().lower()
|
||||
directory_name = 'codeql-analysis-' + package + '-debug'
|
||||
file_name = 'codeql-db-' + package + '-debug-0.sarif'
|
||||
sarif_path = os.path.join('Build', directory_name, file_name)
|
||||
|
||||
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
|
||||
if os.path.isfile(sarif_path):
|
||||
print(f'upload_sarif_file=true', file=fh)
|
||||
print(f'sarif_file_path={sarif_path}', file=fh)
|
||||
else:
|
||||
print(f'upload_sarif_file=false', file=fh)
|
||||
|
||||
- name: Upload CodeQL Results (SARIF) As An Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
if: steps.env_data.outputs.upload_sarif_file == 'true'
|
||||
with:
|
||||
name: ${{ matrix.Package }}-CodeQL-SARIF
|
||||
path: ${{ steps.env_data.outputs.sarif_file_path }}
|
||||
retention-days: 14
|
||||
if-no-files-found: warn
|
||||
|
||||
- name: Upload CodeQL Results (SARIF) To GitHub Code Scanning
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
if: steps.env_data.outputs.upload_sarif_file == 'true'
|
||||
with:
|
||||
# Path to SARIF file relative to the root of the repository.
|
||||
sarif_file: ${{ steps.env_data.outputs.sarif_file_path }}
|
||||
# Optional category for the results. Used to differentiate multiple results for one commit.
|
||||
# Each package is a separate category.
|
||||
category: ${{ matrix.Package }}
|
44
.github/workflows/stale.yml
vendored
Normal file
44
.github/workflows/stale.yml
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
# This workflow warns and then closes issues and PRs that have had no activity
|
||||
# for a specified amount of time.
|
||||
#
|
||||
# For more information, see:
|
||||
# https://github.com/actions/stale
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
|
||||
name: Stale Check
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# At 23:35 on every day-of-week from Sunday through Saturday
|
||||
# https://crontab.guru/#35_23_*_*_0-6
|
||||
- cron: '35 23 * * 0-6'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
name: Stale
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Check for Stale Items
|
||||
uses: actions/stale@v8
|
||||
with:
|
||||
days-before-issue-close: -1
|
||||
days-before-issue-stale: -1
|
||||
days-before-pr-stale: 60
|
||||
days-before-pr-close: 7
|
||||
stale-pr-message: >
|
||||
This PR has been automatically marked as stale because it has not had
|
||||
activity in 60 days. It will be closed if no further activity occurs within
|
||||
7 days. Thank you for your contributions.
|
||||
close-pr-message: >
|
||||
This pull request has been automatically been closed because it did not have any
|
||||
activity in 60 days and no follow up within 7 days after being marked stale.
|
||||
Thank you for your contributions.
|
||||
stale-pr-label: stale
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -32,3 +32,6 @@
|
||||
[submodule "MdePkg/Library/MipiSysTLib/mipisyst"]
|
||||
path = MdePkg/Library/MipiSysTLib/mipisyst
|
||||
url = https://github.com/MIPI-Alliance/public-mipi-sys-t.git
|
||||
[submodule "CryptoPkg/Library/MbedTlsLib/mbedtls"]
|
||||
path = CryptoPkg/Library/MbedTlsLib/mbedtls
|
||||
url = https://github.com/ARMmbed/mbedtls
|
||||
|
@ -7,12 +7,27 @@
|
||||
##
|
||||
import os
|
||||
import logging
|
||||
import sys
|
||||
from edk2toolext.environment import shell_environment
|
||||
from edk2toolext.invocables.edk2_ci_build import CiBuildSettingsManager
|
||||
from edk2toolext.invocables.edk2_setup import SetupSettingsManager, RequiredSubmodule
|
||||
from edk2toolext.invocables.edk2_update import UpdateSettingsManager
|
||||
from edk2toolext.invocables.edk2_pr_eval import PrEvalSettingsManager
|
||||
from edk2toollib.utility_functions import GetHostInfo
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
try:
|
||||
# Temporarily needed until edk2 can update to the latest edk2-pytools
|
||||
# that has the CodeQL helpers.
|
||||
#
|
||||
# May not be present until submodules are populated.
|
||||
#
|
||||
root = Path(__file__).parent.parent.resolve()
|
||||
sys.path.append(str(root/'BaseTools'/'Plugin'/'CodeQL'/'integration'))
|
||||
import stuart_codeql as codeql_helpers
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManager, PrEvalSettingsManager):
|
||||
@ -34,6 +49,11 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
|
||||
group.add_argument("-force_piptools", "--fpt", dest="force_piptools", action="store_true", default=False, help="Force the system to use pip tools")
|
||||
group.add_argument("-no_piptools", "--npt", dest="no_piptools", action="store_true", default=False, help="Force the system to not use pip tools")
|
||||
|
||||
try:
|
||||
codeql_helpers.add_command_line_option(parserObj)
|
||||
except NameError:
|
||||
pass
|
||||
|
||||
def RetrieveCommandLineOptions(self, args):
|
||||
super().RetrieveCommandLineOptions(args)
|
||||
if args.force_piptools:
|
||||
@ -41,6 +61,11 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
|
||||
if args.no_piptools:
|
||||
self.UseBuiltInBaseTools = False
|
||||
|
||||
try:
|
||||
self.codeql = codeql_helpers.is_codeql_enabled_on_command_line(args)
|
||||
except NameError:
|
||||
pass
|
||||
|
||||
# ####################################################################################### #
|
||||
# Default Support for this Ci Build #
|
||||
# ####################################################################################### #
|
||||
@ -169,6 +194,17 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
|
||||
else:
|
||||
logging.warning("Falling back to using in-tree BaseTools")
|
||||
|
||||
try:
|
||||
scopes += codeql_helpers.get_scopes(self.codeql)
|
||||
|
||||
if self.codeql:
|
||||
shell_environment.GetBuildVars().SetValue(
|
||||
"STUART_CODEQL_AUDIT_ONLY",
|
||||
"TRUE",
|
||||
"Set in CISettings.py")
|
||||
except NameError:
|
||||
pass
|
||||
|
||||
self.ActualScopes = scopes
|
||||
return self.ActualScopes
|
||||
|
||||
@ -199,6 +235,8 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
|
||||
"MdePkg/Library/BaseFdtLib/libfdt", False))
|
||||
rs.append(RequiredSubmodule(
|
||||
"MdePkg/Library/MipiSysTLib/mipisyst", False))
|
||||
rs.append(RequiredSubmodule(
|
||||
"CryptoPkg/Library/MbedTlsLib/mbedtls", False))
|
||||
return rs
|
||||
|
||||
def GetName(self):
|
||||
|
@ -10,7 +10,7 @@ import logging
|
||||
import os
|
||||
from edk2toolext.environment.plugintypes.ci_build_plugin import ICiBuildPlugin
|
||||
from edk2toollib.uefi.edk2.parsers.dsc_parser import DscParser
|
||||
from edk2toollib.uefi.edk2.parsers.inf_parser import InfParser
|
||||
from edk2toollib.uefi.edk2.parsers.inf_parser import InfParser, AllPhases
|
||||
from edk2toolext.environment.var_dict import VarDict
|
||||
|
||||
|
||||
@ -116,8 +116,9 @@ class HostUnitTestDscCompleteCheck(ICiBuildPlugin):
|
||||
# should compile test a library that is declared type HOST_APPLICATION
|
||||
pass
|
||||
|
||||
elif len(infp.SupportedPhases) > 0 and \
|
||||
"HOST_APPLICATION" in infp.SupportedPhases:
|
||||
elif (len(infp.SupportedPhases) > 0 and
|
||||
"HOST_APPLICATION" in infp.SupportedPhases and
|
||||
infp.SupportedPhases != AllPhases):
|
||||
# should compile test a library that supports HOST_APPLICATION but
|
||||
# require it to be an explicit opt-in
|
||||
pass
|
||||
|
@ -110,7 +110,7 @@ class UncrustifyCheck(ICiBuildPlugin):
|
||||
# A package can add any additional paths with "AdditionalIncludePaths"
|
||||
# A package can remove any of these paths with "IgnoreStandardPaths"
|
||||
#
|
||||
STANDARD_PLUGIN_DEFINED_PATHS = ("*.c", "*.h")
|
||||
STANDARD_PLUGIN_DEFINED_PATHS = ("*.c", "*.h", "*.cpp")
|
||||
|
||||
#
|
||||
# The Uncrustify application path should set in this environment variable
|
||||
@ -299,7 +299,7 @@ class UncrustifyCheck(ICiBuildPlugin):
|
||||
If git is not found, an empty list will be returned.
|
||||
"""
|
||||
if not shutil.which("git"):
|
||||
logging.warn(
|
||||
logging.warning(
|
||||
"Git is not found on this system. Git submodule paths will not be considered.")
|
||||
return []
|
||||
|
||||
@ -325,7 +325,7 @@ class UncrustifyCheck(ICiBuildPlugin):
|
||||
If git is not found, an empty list will be returned.
|
||||
"""
|
||||
if not shutil.which("git"):
|
||||
logging.warn(
|
||||
logging.warning(
|
||||
"Git is not found on this system. Git submodule paths will not be considered.")
|
||||
return []
|
||||
|
||||
@ -372,9 +372,9 @@ class UncrustifyCheck(ICiBuildPlugin):
|
||||
file_template_path = pathlib.Path(os.path.join(self._plugin_path, file_template_name))
|
||||
self._file_template_contents = file_template_path.read_text()
|
||||
except KeyError:
|
||||
logging.warn("A file header template is not specified in the config file.")
|
||||
logging.warning("A file header template is not specified in the config file.")
|
||||
except FileNotFoundError:
|
||||
logging.warn("The specified file header template file was not found.")
|
||||
logging.warning("The specified file header template file was not found.")
|
||||
try:
|
||||
func_template_name = parser["dummy_section"]["cmt_insert_func_header"]
|
||||
|
||||
@ -384,9 +384,9 @@ class UncrustifyCheck(ICiBuildPlugin):
|
||||
func_template_path = pathlib.Path(os.path.join(self._plugin_path, func_template_name))
|
||||
self._func_template_contents = func_template_path.read_text()
|
||||
except KeyError:
|
||||
logging.warn("A function header template is not specified in the config file.")
|
||||
logging.warning("A function header template is not specified in the config file.")
|
||||
except FileNotFoundError:
|
||||
logging.warn("The specified function header template file was not found.")
|
||||
logging.warning("The specified function header template file was not found.")
|
||||
|
||||
def _initialize_app_info(self) -> None:
|
||||
"""
|
||||
|
@ -215,7 +215,7 @@ indent_braces = false
|
||||
indent_braces_no_class = false
|
||||
indent_braces_no_func = true
|
||||
indent_braces_no_struct = false
|
||||
indent_class = false
|
||||
indent_class = true
|
||||
indent_class_colon = false
|
||||
indent_cmt_with_tabs = false # Whether to indent comments that are not at a brace level with tabs on
|
||||
# a tabstop. Requires indent_with_tabs=2. If false, will use spaces.
|
||||
@ -223,7 +223,7 @@ indent_col1_comment = true
|
||||
indent_col1_multi_string_literal= true
|
||||
indent_comma_paren = true
|
||||
indent_else_if = true
|
||||
indent_extern = false
|
||||
indent_extern = true
|
||||
indent_first_bool_expr = true
|
||||
|
||||
indent_func_def_param_paren_pos_threshold = 0
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,31 +0,0 @@
|
||||
## @file
|
||||
# Application to present AArch64 cpu information.
|
||||
#
|
||||
# Based on HelloWorld:
|
||||
# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2023, Linaro Ltd. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010019
|
||||
BASE_NAME = ArmCpuInfo
|
||||
FILE_GUID = b3134491-6502-4faf-a9da-007184e32163
|
||||
MODULE_TYPE = UEFI_APPLICATION
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = UefiMain
|
||||
|
||||
[Sources]
|
||||
ArmCpuInfo.c
|
||||
|
||||
[Packages]
|
||||
ArmPkg/ArmPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
ArmLib
|
||||
UefiApplicationEntryPoint
|
||||
UefiLib
|
@ -328,6 +328,7 @@
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|30|UINT32|0x00000036
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum|26|UINT32|0x00000040
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|27|UINT32|0x00000041
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypVirtIntrNum|28|UINT32|0x0000004A
|
||||
|
||||
#
|
||||
# ARM Generic Watchdog
|
||||
|
@ -168,7 +168,6 @@
|
||||
ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf
|
||||
ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
|
||||
ArmPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf
|
||||
ArmPkg/Application/ArmCpuInfo/ArmCpuInfo.inf
|
||||
|
||||
[Components.AARCH64, Components.ARM]
|
||||
ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.inf
|
||||
|
@ -103,7 +103,9 @@ DispatchCpu (
|
||||
|
||||
ArmCallSmc (&Args);
|
||||
|
||||
if (Args.Arg0 != ARM_SMC_PSCI_RET_SUCCESS) {
|
||||
if (Args.Arg0 == ARM_SMC_PSCI_RET_ALREADY_ON) {
|
||||
Status = EFI_NOT_READY;
|
||||
} else if (Args.Arg0 != ARM_SMC_PSCI_RET_SUCCESS) {
|
||||
DEBUG ((DEBUG_ERROR, "PSCI_CPU_ON call failed: %d\n", Args.Arg0));
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
@ -24,10 +24,17 @@
|
||||
// Coprocessor Trap Register (CPTR)
|
||||
#define AARCH64_CPTR_TFP (1 << 10)
|
||||
|
||||
// ID_AA64MMFR1 - AArch64 Memory Model Feature Register 0 definitions
|
||||
#define AARCH64_MMFR1_VH (0xF << 8)
|
||||
|
||||
// ID_AA64PFR0 - AArch64 Processor Feature Register 0 definitions
|
||||
#define AARCH64_PFR0_FP (0xF << 16)
|
||||
#define AARCH64_PFR0_GIC (0xF << 24)
|
||||
|
||||
// ID_AA64DFR0 - AArch64 Debug Feature Register 0 definitions
|
||||
#define AARCH64_DFR0_TRACEVER (0xFULL << 4)
|
||||
#define AARCH64_DFR0_TRBE (0xFULL << 44)
|
||||
|
||||
// SCR - Secure Configuration Register definitions
|
||||
#define SCR_NS (1 << 0)
|
||||
#define SCR_IRQ (1 << 1)
|
||||
|
@ -45,8 +45,6 @@ typedef enum {
|
||||
ARM_MEMORY_REGION_ATTRIBUTE_DEVICE,
|
||||
} ARM_MEMORY_REGION_ATTRIBUTES;
|
||||
|
||||
#define IS_ARM_MEMORY_REGION_ATTRIBUTES_SECURE(attr) ((UINT32)(attr) & 1)
|
||||
|
||||
typedef struct {
|
||||
EFI_PHYSICAL_ADDRESS PhysicalBase;
|
||||
EFI_VIRTUAL_ADDRESS VirtualBase;
|
||||
@ -766,6 +764,49 @@ ArmHasCcidx (
|
||||
VOID
|
||||
);
|
||||
|
||||
#ifdef MDE_CPU_AARCH64
|
||||
///
|
||||
/// AArch64-only ID Register Helper functions
|
||||
///
|
||||
|
||||
/**
|
||||
Checks whether the CPU implements the Virtualization Host Extensions.
|
||||
|
||||
@retval TRUE FEAT_VHE is implemented.
|
||||
@retval FALSE FEAT_VHE is not mplemented.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmHasVhe (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Checks whether the CPU implements the Trace Buffer Extension.
|
||||
|
||||
@retval TRUE FEAT_TRBE is implemented.
|
||||
@retval FALSE FEAT_TRBE is not mplemented.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmHasTrbe (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Checks whether the CPU implements the Embedded Trace Extension.
|
||||
|
||||
@retval TRUE FEAT_ETE is implemented.
|
||||
@retval FALSE FEAT_ETE is not mplemented.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmHasEte (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif // MDE_CPU_AARCH64
|
||||
|
||||
#ifdef MDE_CPU_ARM
|
||||
///
|
||||
/// AArch32-only ID Register Helper functions
|
||||
|
@ -104,3 +104,49 @@ ArmHasCcidx (
|
||||
Mmfr2 = ArmReadIdAA64Mmfr2 ();
|
||||
return (((Mmfr2 >> 20) & 0xF) == 1) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Checks whether the CPU implements the Virtualization Host Extensions.
|
||||
|
||||
@retval TRUE FEAT_VHE is implemented.
|
||||
@retval FALSE FEAT_VHE is not mplemented.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmHasVhe (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return ((ArmReadIdAA64Mmfr1 () & AARCH64_MMFR1_VH) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
Checks whether the CPU implements the Trace Buffer Extension.
|
||||
|
||||
@retval TRUE FEAT_TRBE is implemented.
|
||||
@retval FALSE FEAT_TRBE is not mplemented.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmHasTrbe (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return ((ArmReadIdAA64Dfr0 () & AARCH64_DFR0_TRBE) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
Checks whether the CPU implements the Embedded Trace Extension.
|
||||
|
||||
@retval TRUE FEAT_ETE is implemented.
|
||||
@retval FALSE FEAT_ETE is not mplemented.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmHasEte (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// The ID_AA64DFR0_EL1.TraceVer field identifies the presence of FEAT_ETE.
|
||||
return ((ArmReadIdAA64Dfr0 () & AARCH64_DFR0_TRACEVER) != 0);
|
||||
}
|
||||
|
@ -169,7 +169,6 @@ PopulateLevel2PageTable (
|
||||
|
||||
// Overwrite the section entry to point to the new Level2 Translation Table
|
||||
*SectionEntry = (TranslationTable & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) |
|
||||
(IS_ARM_MEMORY_REGION_ATTRIBUTES_SECURE (Attributes) ? (1 << 3) : 0) |
|
||||
TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE;
|
||||
} else {
|
||||
// We do not support the other section type (16MB Section)
|
||||
@ -192,7 +191,6 @@ PopulateLevel2PageTable (
|
||||
ZeroMem ((VOID *)TranslationTable, TRANSLATION_TABLE_PAGE_SIZE);
|
||||
|
||||
*SectionEntry = (TranslationTable & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) |
|
||||
(IS_ARM_MEMORY_REGION_ATTRIBUTES_SECURE (Attributes) ? (1 << 3) : 0) |
|
||||
TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE;
|
||||
}
|
||||
|
||||
|
@ -185,7 +185,7 @@ SMBIOS_MISC_TABLE_FUNCTION (MiscBiosVendor) {
|
||||
UINTN VendorStrLen;
|
||||
UINTN VerStrLen;
|
||||
UINTN DateStrLen;
|
||||
UINTN BiosPhysicalSize;
|
||||
UINT64 BiosPhysicalSize;
|
||||
CHAR16 *Vendor;
|
||||
CHAR16 *Version;
|
||||
CHAR16 *ReleaseDate;
|
||||
|
@ -27,8 +27,6 @@
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeLib.h>
|
||||
|
||||
#include <Protocol/RealTimeClock.h>
|
||||
|
||||
#include "PL031RealTimeClock.h"
|
||||
|
||||
STATIC BOOLEAN mPL031Initialized = FALSE;
|
||||
@ -274,9 +272,10 @@ LibSetWakeupTime (
|
||||
@param[in] Event The Event that is being processed
|
||||
@param[in] Context Event Context
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
LibRtcVirtualNotifyEvent (
|
||||
VirtualNotifyEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
@ -309,7 +308,6 @@ LibRtcInitialize (
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE Handle;
|
||||
|
||||
// Initialize RTC Base Address
|
||||
mPL031RtcBase = PcdGet32 (PcdPL031RtcBase);
|
||||
@ -330,23 +328,13 @@ LibRtcInitialize (
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Install the protocol
|
||||
Handle = NULL;
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&Handle,
|
||||
&gEfiRealTimeClockArchProtocolGuid,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Register for the virtual address change event
|
||||
//
|
||||
Status = gBS->CreateEventEx (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
LibRtcVirtualNotifyEvent,
|
||||
VirtualNotifyEvent,
|
||||
NULL,
|
||||
&gEfiEventVirtualAddressChangeGuid,
|
||||
&mRtcVirtualAddrChangeEvent
|
||||
|
@ -37,7 +37,7 @@
|
||||
!if $(TARGET) == RELEASE
|
||||
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
|
||||
!else
|
||||
DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
|
||||
DebugLib|ArmVirtPkg/Library/DebugLibFdtPL011Uart/DebugLibFdtPL011UartRam.inf
|
||||
!endif
|
||||
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
|
||||
|
||||
@ -121,6 +121,7 @@
|
||||
# ARM PL011 UART Driver
|
||||
PL011UartLib|ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf
|
||||
SerialPortLib|ArmVirtPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf
|
||||
FdtSerialPortAddressLib|ArmVirtPkg/Library/FdtSerialPortAddressLib/FdtSerialPortAddressLib.inf
|
||||
|
||||
PeCoffExtraActionLib|ArmPkg/Library/DebugPeCoffExtraActionLib/DebugPeCoffExtraActionLib.inf
|
||||
#PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
|
||||
@ -154,7 +155,7 @@
|
||||
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
|
||||
!endif
|
||||
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
|
||||
RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
|
||||
RngLib|MdeModulePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
|
||||
|
||||
#
|
||||
# Secure Boot dependencies
|
||||
@ -188,6 +189,9 @@
|
||||
PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
|
||||
PeiServicesTablePointerLib|ArmPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
|
||||
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
|
||||
!if $(TARGET) != RELEASE
|
||||
DebugLib|ArmVirtPkg/Library/DebugLibFdtPL011Uart/DebugLibFdtPL011UartFlash.inf
|
||||
!endif
|
||||
|
||||
[LibraryClasses.common.PEI_CORE]
|
||||
PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
|
||||
@ -203,6 +207,9 @@
|
||||
|
||||
PeiServicesTablePointerLib|ArmPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
|
||||
SerialPortLib|ArmVirtPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.inf
|
||||
!if $(TARGET) != RELEASE
|
||||
DebugLib|ArmVirtPkg/Library/DebugLibFdtPL011Uart/DebugLibFdtPL011UartFlash.inf
|
||||
!endif
|
||||
|
||||
[LibraryClasses.common.PEIM]
|
||||
PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
|
||||
@ -218,6 +225,9 @@
|
||||
|
||||
PeiServicesTablePointerLib|ArmPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
|
||||
SerialPortLib|ArmVirtPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.inf
|
||||
!if $(TARGET) != RELEASE
|
||||
DebugLib|ArmVirtPkg/Library/DebugLibFdtPL011Uart/DebugLibFdtPL011UartFlash.inf
|
||||
!endif
|
||||
|
||||
[LibraryClasses.common.DXE_CORE]
|
||||
HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
|
||||
@ -245,7 +255,7 @@
|
||||
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
|
||||
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
|
||||
!if $(TARGET) != RELEASE
|
||||
DebugLib|MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf
|
||||
DebugLib|ArmVirtPkg/Library/DebugLibFdtPL011Uart/DxeRuntimeDebugLibFdtPL011Uart.inf
|
||||
!endif
|
||||
VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
|
||||
|
||||
@ -383,6 +393,10 @@
|
||||
<PcdsFixedAtBuild>
|
||||
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
|
||||
}
|
||||
ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.inf {
|
||||
<PcdsFixedAtBuild>
|
||||
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
|
||||
}
|
||||
OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
|
||||
<PcdsFixedAtBuild>
|
||||
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
|
||||
|
@ -178,6 +178,7 @@
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypVirtIntrNum|0x0
|
||||
|
||||
#
|
||||
# ARM General Interrupt Controller
|
||||
|
@ -169,6 +169,7 @@ READ_LOCK_STATUS = TRUE
|
||||
INF ShellPkg/Application/Shell/Shell.inf
|
||||
INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
|
||||
INF ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf
|
||||
INF ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.inf
|
||||
INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
|
||||
|
||||
#
|
||||
|
@ -77,6 +77,9 @@
|
||||
PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
|
||||
PlatformHookLib|ArmVirtPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.inf
|
||||
SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
|
||||
!if $(TARGET) != RELEASE
|
||||
DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
|
||||
!endif
|
||||
|
||||
HwInfoParserLib|DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf
|
||||
DynamicPlatRepoLib|DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib.inf
|
||||
@ -88,6 +91,14 @@
|
||||
PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
|
||||
PlatformHookLib|ArmVirtPkg/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.inf
|
||||
SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
|
||||
!if $(TARGET) != RELEASE
|
||||
DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
|
||||
!endif
|
||||
|
||||
[LibraryClasses.common.DXE_RUNTIME_DRIVER]
|
||||
!if $(TARGET) != RELEASE
|
||||
DebugLib|MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf
|
||||
!endif
|
||||
|
||||
[LibraryClasses.common.UEFI_DRIVER]
|
||||
UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
|
||||
@ -183,6 +194,7 @@
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypVirtIntrNum|0x0
|
||||
|
||||
#
|
||||
# ARM General Interrupt Controller
|
||||
|
@ -125,5 +125,13 @@
|
||||
], # words to extend to the dictionary for this package
|
||||
"IgnoreStandardPaths": [], # Standard Plugin defined paths that should be ignore
|
||||
"AdditionalIncludePaths": [] # Additional paths to spell check (wildcards supported)
|
||||
},
|
||||
|
||||
"DebugMacroCheck": {
|
||||
"StringSubstitutions": {
|
||||
# DynamicTablesPkg/Include/ConfigurationManagerObject.h
|
||||
# Reason: Expansion of macro that contains a print specifier.
|
||||
"FMT_CM_OBJECT_ID": "0x%lx"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
[LibraryClasses]
|
||||
ArmVirtMemInfoLib|Include/Library/ArmVirtMemInfoLib.h
|
||||
FdtSerialPortAddressLib|Include/Library/FdtSerialPortAddressLib.h
|
||||
|
||||
[Guids.common]
|
||||
gArmVirtTokenSpaceGuid = { 0x0B6F5CA7, 0x4F53, 0x445A, { 0xB7, 0x6E, 0x2E, 0x36, 0x5B, 0x80, 0x63, 0x66 } }
|
||||
|
@ -253,6 +253,7 @@
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypVirtIntrNum|0x0
|
||||
|
||||
#
|
||||
# ARM General Interrupt Controller
|
||||
|
@ -103,6 +103,7 @@ READ_LOCK_STATUS = TRUE
|
||||
INF ShellPkg/Application/Shell/Shell.inf
|
||||
INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
|
||||
INF ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf
|
||||
INF ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.inf
|
||||
INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
|
||||
|
||||
#
|
||||
|
@ -214,6 +214,7 @@
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypVirtIntrNum|0x0
|
||||
|
||||
#
|
||||
# ARM General Interrupt Controller
|
||||
|
@ -29,6 +29,9 @@
|
||||
|
||||
[LibraryClasses]
|
||||
SerialPortLib|OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.inf
|
||||
!if $(TARGET) != RELEASE
|
||||
DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
|
||||
!endif
|
||||
RealTimeClockLib|OvmfPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf
|
||||
XenHypercallLib|OvmfPkg/Library/XenHypercallLib/XenHypercallLib.inf
|
||||
|
||||
@ -52,6 +55,11 @@
|
||||
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
|
||||
TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTpmPlatformHierarchyLib.inf
|
||||
|
||||
[LibraryClasses.common.DXE_RUNTIME_DRIVER]
|
||||
!if $(TARGET) != RELEASE
|
||||
DebugLib|MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf
|
||||
!endif
|
||||
|
||||
[LibraryClasses.common.UEFI_DRIVER]
|
||||
UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
|
||||
|
||||
@ -118,6 +126,7 @@
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum|0x0
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypVirtIntrNum|0x0
|
||||
|
||||
#
|
||||
# ARM General Interrupt Controller
|
||||
@ -146,6 +155,9 @@
|
||||
PrePiHobListPointerLib|ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf
|
||||
MemoryAllocationLib|EmbeddedPkg/Library/PrePiMemoryAllocationLib/PrePiMemoryAllocationLib.inf
|
||||
SerialPortLib|OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.inf
|
||||
!if $(TARGET) != RELEASE
|
||||
DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
|
||||
!endif
|
||||
}
|
||||
|
||||
#
|
||||
|
@ -180,6 +180,7 @@ READ_LOCK_STATUS = TRUE
|
||||
INF ShellPkg/Application/Shell/Shell.inf
|
||||
INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
|
||||
INF ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf
|
||||
INF ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.inf
|
||||
INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
|
||||
|
||||
#
|
||||
|
@ -1,6 +1,6 @@
|
||||
/** @file
|
||||
GUID for the HOB that caches the base address of the PL011 serial port, for
|
||||
when PCD access is not available.
|
||||
GUID for the HOB that caches the base address(es) of the PL011 serial port(s),
|
||||
for when PCD access is not available.
|
||||
|
||||
Copyright (C) 2014, Red Hat, Inc.
|
||||
|
||||
@ -18,4 +18,15 @@
|
||||
|
||||
extern EFI_GUID gEarlyPL011BaseAddressGuid;
|
||||
|
||||
typedef struct {
|
||||
//
|
||||
// for SerialPortLib and console IO
|
||||
//
|
||||
UINT64 ConsoleAddress;
|
||||
//
|
||||
// for DebugLib; may equal ConsoleAddress if there's only one PL011 UART
|
||||
//
|
||||
UINT64 DebugAddress;
|
||||
} EARLY_PL011_BASE_ADDRESS;
|
||||
|
||||
#endif
|
||||
|
83
ArmVirtPkg/Include/Library/FdtSerialPortAddressLib.h
Normal file
83
ArmVirtPkg/Include/Library/FdtSerialPortAddressLib.h
Normal file
@ -0,0 +1,83 @@
|
||||
/** @file
|
||||
Determine the base addresses of serial ports from the Device Tree.
|
||||
|
||||
Copyright (C) Red Hat
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#ifndef FDT_SERIAL_PORT_ADDRESS_LIB_H_
|
||||
#define FDT_SERIAL_PORT_ADDRESS_LIB_H_
|
||||
|
||||
#include <Base.h>
|
||||
|
||||
typedef struct {
|
||||
UINTN NumberOfPorts;
|
||||
UINT64 BaseAddress[2];
|
||||
} FDT_SERIAL_PORTS;
|
||||
|
||||
/**
|
||||
Collect the first ARRAY_SIZE (Ports->BaseAddress) serial ports into Ports from
|
||||
DeviceTree.
|
||||
|
||||
@param[in] DeviceTree The flat device tree (FDT) to scan.
|
||||
|
||||
@param[in] Compatible Look for Compatible in the "compatible" property of the
|
||||
scanned nodes.
|
||||
|
||||
@param[out] Ports On successful return, Ports->NumberOfPorts contains the
|
||||
number of serial ports found; it is (a) positive and
|
||||
(b) at most ARRAY_SIZE (Ports->BaseAddress). If the FDT
|
||||
had more serial ports, those are not reported. On
|
||||
error, the contents of Ports are indeterminate.
|
||||
|
||||
@retval RETURN_INVALID_PARAMETER DeviceTree does not point to a valid FDT
|
||||
header.
|
||||
|
||||
@retval RETURN_NOT_FOUND No compatible and enabled serial port has
|
||||
been found.
|
||||
|
||||
@retval RETURN_SUCCESS At least one compatible and enabled serial
|
||||
port has been found; Ports has been filled
|
||||
in.
|
||||
**/
|
||||
RETURN_STATUS
|
||||
EFIAPI
|
||||
FdtSerialGetPorts (
|
||||
IN CONST VOID *DeviceTree,
|
||||
IN CONST CHAR8 *Compatible,
|
||||
OUT FDT_SERIAL_PORTS *Ports
|
||||
);
|
||||
|
||||
/**
|
||||
Fetch the base address of the serial port identified in the "stdout-path"
|
||||
property of the "/chosen" node in DeviceTree.
|
||||
|
||||
@param[in] DeviceTree The flat device tree (FDT) to scan.
|
||||
|
||||
@param[out] BaseAddress On success, the base address of the preferred serial
|
||||
port (to be used as console). On error, BaseAddress
|
||||
is not modified.
|
||||
|
||||
@retval RETURN_INVALID_PARAMETER DeviceTree does not point to a valid FDT
|
||||
header.
|
||||
|
||||
@retval RETURN_NOT_FOUND No enabled console port has been found.
|
||||
|
||||
@retval RETURN_PROTOCOL_ERROR The first (or only) node path in the
|
||||
"stdout-path" property is an empty string.
|
||||
|
||||
@retval RETURN_PROTOCOL_ERROR The console port has been found in the FDT,
|
||||
but its base address is not correctly
|
||||
represented.
|
||||
|
||||
@retval RETURN_SUCCESS BaseAddress has been populated.
|
||||
**/
|
||||
RETURN_STATUS
|
||||
EFIAPI
|
||||
FdtSerialGetConsolePort (
|
||||
IN CONST VOID *DeviceTree,
|
||||
OUT UINT64 *BaseAddress
|
||||
);
|
||||
|
||||
#endif
|
@ -35,6 +35,7 @@ ArmVirtTimerFdtClientLibConstructor (
|
||||
CONST INTERRUPT_PROPERTY *InterruptProp;
|
||||
UINT32 PropSize;
|
||||
INT32 SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum;
|
||||
INT32 HypVirtIntrNum;
|
||||
RETURN_STATUS PcdStatus;
|
||||
|
||||
Status = gBS->LocateProtocol (
|
||||
@ -66,10 +67,10 @@ ArmVirtTimerFdtClientLibConstructor (
|
||||
}
|
||||
|
||||
//
|
||||
// - interrupts : Interrupt list for secure, non-secure, virtual and
|
||||
// hypervisor timers, in that order.
|
||||
// - interrupts : Interrupt list for secure, non-secure, virtual,
|
||||
// hypervisor and hypervisor virtual timers, in that order.
|
||||
//
|
||||
ASSERT (PropSize == 36 || PropSize == 48);
|
||||
ASSERT (PropSize >= 36);
|
||||
|
||||
SecIntrNum = SwapBytes32 (InterruptProp[0].Number)
|
||||
+ (InterruptProp[0].Type ? 16 : 0);
|
||||
@ -79,6 +80,8 @@ ArmVirtTimerFdtClientLibConstructor (
|
||||
+ (InterruptProp[2].Type ? 16 : 0);
|
||||
HypIntrNum = PropSize < 48 ? 0 : SwapBytes32 (InterruptProp[3].Number)
|
||||
+ (InterruptProp[3].Type ? 16 : 0);
|
||||
HypVirtIntrNum = PropSize < 60 ? 0 : SwapBytes32 (InterruptProp[4].Number)
|
||||
+ (InterruptProp[4].Type ? 16 : 0);
|
||||
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
@ -97,6 +100,8 @@ ArmVirtTimerFdtClientLibConstructor (
|
||||
ASSERT_RETURN_ERROR (PcdStatus);
|
||||
PcdStatus = PcdSet32S (PcdArmArchTimerHypIntrNum, HypIntrNum);
|
||||
ASSERT_RETURN_ERROR (PcdStatus);
|
||||
PcdStatus = PcdSet32S (PcdArmArchTimerHypVirtIntrNum, HypVirtIntrNum);
|
||||
ASSERT_RETURN_ERROR (PcdStatus);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerIntrNum
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypVirtIntrNum
|
||||
|
||||
[Depex]
|
||||
gFdtClientProtocolGuid
|
||||
|
355
ArmVirtPkg/Library/DebugLibFdtPL011Uart/DebugLib.c
Normal file
355
ArmVirtPkg/Library/DebugLibFdtPL011Uart/DebugLib.c
Normal file
@ -0,0 +1,355 @@
|
||||
/** @file
|
||||
Originally copied from "MdePkg/Library/BaseDebugLibSerialPort/DebugLib.c" at
|
||||
commit f36e1ec1f0a5, and customized for:
|
||||
|
||||
- RAM vs. flash dependent PL011 UART initialization,
|
||||
|
||||
- direct PL011 UART access, with the base address taken from the device tree
|
||||
such that the debug output be separate from the SerialPortLib / UEFI console
|
||||
traffic.
|
||||
|
||||
Both of these customizations are hidden behind DebugLibFdtPL011UartWrite(),
|
||||
which replaces SerialPortWrite().
|
||||
|
||||
Copyright (C) Red Hat
|
||||
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include <Base.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugPrintErrorLevelLib.h>
|
||||
|
||||
#include "Write.h"
|
||||
|
||||
//
|
||||
// Define the maximum debug and assert message length that this library supports
|
||||
//
|
||||
#define MAX_DEBUG_MESSAGE_LENGTH 0x100
|
||||
|
||||
//
|
||||
// VA_LIST can not initialize to NULL for all compiler, so we use this to
|
||||
// indicate a null VA_LIST
|
||||
//
|
||||
VA_LIST mVaListNull;
|
||||
|
||||
/**
|
||||
Prints a debug message to the debug output device if the specified error level is enabled.
|
||||
|
||||
If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
|
||||
GetDebugPrintErrorLevel (), then print the message specified by Format and the
|
||||
associated variable argument list to the debug output device.
|
||||
|
||||
If Format is NULL, then ASSERT().
|
||||
|
||||
@param ErrorLevel The error level of the debug message.
|
||||
@param Format Format string for the debug message to print.
|
||||
@param ... Variable argument list whose contents are accessed
|
||||
based on the format string specified by Format.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
DebugPrint (
|
||||
IN UINTN ErrorLevel,
|
||||
IN CONST CHAR8 *Format,
|
||||
...
|
||||
)
|
||||
{
|
||||
VA_LIST Marker;
|
||||
|
||||
VA_START (Marker, Format);
|
||||
DebugVPrint (ErrorLevel, Format, Marker);
|
||||
VA_END (Marker);
|
||||
}
|
||||
|
||||
/**
|
||||
Prints a debug message to the debug output device if the specified
|
||||
error level is enabled base on Null-terminated format string and a
|
||||
VA_LIST argument list or a BASE_LIST argument list.
|
||||
|
||||
If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
|
||||
GetDebugPrintErrorLevel (), then print the message specified by Format and
|
||||
the associated variable argument list to the debug output device.
|
||||
|
||||
If Format is NULL, then ASSERT().
|
||||
|
||||
@param ErrorLevel The error level of the debug message.
|
||||
@param Format Format string for the debug message to print.
|
||||
@param VaListMarker VA_LIST marker for the variable argument list.
|
||||
@param BaseListMarker BASE_LIST marker for the variable argument list.
|
||||
|
||||
**/
|
||||
VOID
|
||||
DebugPrintMarker (
|
||||
IN UINTN ErrorLevel,
|
||||
IN CONST CHAR8 *Format,
|
||||
IN VA_LIST VaListMarker,
|
||||
IN BASE_LIST BaseListMarker
|
||||
)
|
||||
{
|
||||
CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];
|
||||
|
||||
//
|
||||
// If Format is NULL, then ASSERT().
|
||||
//
|
||||
ASSERT (Format != NULL);
|
||||
|
||||
//
|
||||
// Check driver debug mask value and global mask
|
||||
//
|
||||
if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Convert the DEBUG() message to an ASCII String
|
||||
//
|
||||
if (BaseListMarker == NULL) {
|
||||
AsciiVSPrint (Buffer, sizeof (Buffer), Format, VaListMarker);
|
||||
} else {
|
||||
AsciiBSPrint (Buffer, sizeof (Buffer), Format, BaseListMarker);
|
||||
}
|
||||
|
||||
//
|
||||
// Send the print string to a Serial Port
|
||||
//
|
||||
DebugLibFdtPL011UartWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
Prints a debug message to the debug output device if the specified
|
||||
error level is enabled.
|
||||
|
||||
If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
|
||||
GetDebugPrintErrorLevel (), then print the message specified by Format and
|
||||
the associated variable argument list to the debug output device.
|
||||
|
||||
If Format is NULL, then ASSERT().
|
||||
|
||||
@param ErrorLevel The error level of the debug message.
|
||||
@param Format Format string for the debug message to print.
|
||||
@param VaListMarker VA_LIST marker for the variable argument list.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
DebugVPrint (
|
||||
IN UINTN ErrorLevel,
|
||||
IN CONST CHAR8 *Format,
|
||||
IN VA_LIST VaListMarker
|
||||
)
|
||||
{
|
||||
DebugPrintMarker (ErrorLevel, Format, VaListMarker, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
Prints a debug message to the debug output device if the specified
|
||||
error level is enabled.
|
||||
This function use BASE_LIST which would provide a more compatible
|
||||
service than VA_LIST.
|
||||
|
||||
If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
|
||||
GetDebugPrintErrorLevel (), then print the message specified by Format and
|
||||
the associated variable argument list to the debug output device.
|
||||
|
||||
If Format is NULL, then ASSERT().
|
||||
|
||||
@param ErrorLevel The error level of the debug message.
|
||||
@param Format Format string for the debug message to print.
|
||||
@param BaseListMarker BASE_LIST marker for the variable argument list.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
DebugBPrint (
|
||||
IN UINTN ErrorLevel,
|
||||
IN CONST CHAR8 *Format,
|
||||
IN BASE_LIST BaseListMarker
|
||||
)
|
||||
{
|
||||
DebugPrintMarker (ErrorLevel, Format, mVaListNull, BaseListMarker);
|
||||
}
|
||||
|
||||
/**
|
||||
Prints an assert message containing a filename, line number, and description.
|
||||
This may be followed by a breakpoint or a dead loop.
|
||||
|
||||
Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"
|
||||
to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of
|
||||
PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if
|
||||
DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then
|
||||
CpuDeadLoop() is called. If neither of these bits are set, then this function
|
||||
returns immediately after the message is printed to the debug output device.
|
||||
DebugAssert() must actively prevent recursion. If DebugAssert() is called while
|
||||
processing another DebugAssert(), then DebugAssert() must return immediately.
|
||||
|
||||
If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
|
||||
If Description is NULL, then a <Description> string of "(NULL) Description" is printed.
|
||||
|
||||
@param FileName The pointer to the name of the source file that generated the assert condition.
|
||||
@param LineNumber The line number in the source file that generated the assert condition
|
||||
@param Description The pointer to the description of the assert condition.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
DebugAssert (
|
||||
IN CONST CHAR8 *FileName,
|
||||
IN UINTN LineNumber,
|
||||
IN CONST CHAR8 *Description
|
||||
)
|
||||
{
|
||||
CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];
|
||||
|
||||
//
|
||||
// Generate the ASSERT() message in Ascii format
|
||||
//
|
||||
AsciiSPrint (Buffer, sizeof (Buffer), "ASSERT [%a] %a(%d): %a\n", gEfiCallerBaseName, FileName, LineNumber, Description);
|
||||
|
||||
//
|
||||
// Send the print string to the Console Output device
|
||||
//
|
||||
DebugLibFdtPL011UartWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
|
||||
|
||||
//
|
||||
// Generate a Breakpoint, DeadLoop, or NOP based on PCD settings
|
||||
//
|
||||
if ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {
|
||||
CpuBreakpoint ();
|
||||
} else if ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {
|
||||
CpuDeadLoop ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer.
|
||||
|
||||
This function fills Length bytes of Buffer with the value specified by
|
||||
PcdDebugClearMemoryValue, and returns Buffer.
|
||||
|
||||
If Buffer is NULL, then ASSERT().
|
||||
If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
|
||||
|
||||
@param Buffer The pointer to the target buffer to be filled with PcdDebugClearMemoryValue.
|
||||
@param Length The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue.
|
||||
|
||||
@return Buffer The pointer to the target buffer filled with PcdDebugClearMemoryValue.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
EFIAPI
|
||||
DebugClearMemory (
|
||||
OUT VOID *Buffer,
|
||||
IN UINTN Length
|
||||
)
|
||||
{
|
||||
//
|
||||
// If Buffer is NULL, then ASSERT().
|
||||
//
|
||||
ASSERT (Buffer != NULL);
|
||||
|
||||
//
|
||||
// SetMem() checks for the the ASSERT() condition on Length and returns Buffer
|
||||
//
|
||||
return SetMem (Buffer, Length, PcdGet8 (PcdDebugClearMemoryValue));
|
||||
}
|
||||
|
||||
/**
|
||||
Returns TRUE if ASSERT() macros are enabled.
|
||||
|
||||
This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of
|
||||
PcdDebugProperyMask is set. Otherwise FALSE is returned.
|
||||
|
||||
@retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set.
|
||||
@retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
DebugAssertEnabled (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns TRUE if DEBUG() macros are enabled.
|
||||
|
||||
This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of
|
||||
PcdDebugProperyMask is set. Otherwise FALSE is returned.
|
||||
|
||||
@retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set.
|
||||
@retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
DebugPrintEnabled (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns TRUE if DEBUG_CODE() macros are enabled.
|
||||
|
||||
This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of
|
||||
PcdDebugProperyMask is set. Otherwise FALSE is returned.
|
||||
|
||||
@retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set.
|
||||
@retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
DebugCodeEnabled (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled.
|
||||
|
||||
This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of
|
||||
PcdDebugProperyMask is set. Otherwise FALSE is returned.
|
||||
|
||||
@retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set.
|
||||
@retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
DebugClearMemoryEnabled (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns TRUE if any one of the bit is set both in ErrorLevel and PcdFixedDebugPrintErrorLevel.
|
||||
|
||||
This function compares the bit mask of ErrorLevel and PcdFixedDebugPrintErrorLevel.
|
||||
|
||||
@retval TRUE Current ErrorLevel is supported.
|
||||
@retval FALSE Current ErrorLevel is not supported.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
DebugPrintLevelEnabled (
|
||||
IN CONST UINTN ErrorLevel
|
||||
)
|
||||
{
|
||||
return (BOOLEAN)((ErrorLevel & PcdGet32 (PcdFixedDebugPrintErrorLevel)) != 0);
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
## @file
|
||||
# DebugLib instance that produces debug output directly via PL011UartLib.
|
||||
#
|
||||
# If there are at least two PL011 UARTs in the device tree, and the /chosen
|
||||
# node's "stdout-path" property references one PL011 UART, then both raw
|
||||
# SerialPortLib IO, and -- via SerialDxe -- UEFI console IO, will occur on that
|
||||
# UART; and this DebugLib instance will produce output on a *different* UART.
|
||||
#
|
||||
# This instance is suitable for modules that may run from flash or RAM.
|
||||
#
|
||||
# Copyright (C) Red Hat
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 1.27
|
||||
BASE_NAME = DebugLibFdtPL011UartFlash
|
||||
FILE_GUID = 43A4C56B-D071-4CE0-A157-9D59E6161DEC
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = DebugLib|SEC PEI_CORE PEIM
|
||||
|
||||
[Sources]
|
||||
DebugLib.c
|
||||
Flash.c
|
||||
Write.h
|
||||
|
||||
[Packages]
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
ArmVirtPkg/ArmVirtPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
DebugPrintErrorLevelLib
|
||||
FdtSerialPortAddressLib # Flash.c
|
||||
PL011UartLib
|
||||
PcdLib
|
||||
PrintLib
|
||||
|
||||
[Pcd]
|
||||
gArmVirtTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress # Flash.c
|
||||
gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue
|
||||
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask
|
||||
gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel
|
||||
|
||||
[FixedPcd]
|
||||
gArmPlatformTokenSpaceGuid.PL011UartClkInHz
|
||||
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
|
||||
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
|
||||
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
|
||||
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
|
@ -0,0 +1,60 @@
|
||||
## @file
|
||||
# DebugLib instance that produces debug output directly via PL011UartLib.
|
||||
#
|
||||
# If there are at least two PL011 UARTs in the device tree, and the /chosen
|
||||
# node's "stdout-path" property references one PL011 UART, then both raw
|
||||
# SerialPortLib IO, and -- via SerialDxe -- UEFI console IO, will occur on that
|
||||
# UART; and this DebugLib instance will produce output on a *different* UART.
|
||||
#
|
||||
# This instance is suitable for modules that can only run from RAM (except
|
||||
# DXE_RUNTIME_DRIVER).
|
||||
#
|
||||
# Copyright (C) Red Hat
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 1.27
|
||||
BASE_NAME = DebugLibFdtPL011UartRam
|
||||
FILE_GUID = 0584DE55-9C4C-49C1-ADA0-F62C9C1F3600
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = DebugLib|DXE_CORE SMM_CORE MM_CORE_STANDALONE DXE_DRIVER DXE_SMM_DRIVER SMM_DRIVER MM_STANDALONE UEFI_DRIVER UEFI_APPLICATION
|
||||
CONSTRUCTOR = DebugLibFdtPL011UartRamConstructor
|
||||
|
||||
[Sources]
|
||||
DebugLib.c
|
||||
Ram.c
|
||||
Ram.h
|
||||
RamNonRuntime.c
|
||||
Write.h
|
||||
|
||||
[Packages]
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
ArmVirtPkg/ArmVirtPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
DebugPrintErrorLevelLib
|
||||
HobLib # Ram.c
|
||||
PL011UartLib
|
||||
PcdLib
|
||||
PrintLib
|
||||
|
||||
[Pcd]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue
|
||||
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask
|
||||
gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel
|
||||
|
||||
[FixedPcd]
|
||||
gArmPlatformTokenSpaceGuid.PL011UartClkInHz
|
||||
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
|
||||
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
|
||||
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
|
||||
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
|
||||
|
||||
[Guids]
|
||||
gEarlyPL011BaseAddressGuid # Ram.c
|
@ -0,0 +1,61 @@
|
||||
## @file
|
||||
# DebugLib instance that produces debug output directly via PL011UartLib.
|
||||
#
|
||||
# If there are at least two PL011 UARTs in the device tree, and the /chosen
|
||||
# node's "stdout-path" property references one PL011 UART, then both raw
|
||||
# SerialPortLib IO, and -- via SerialDxe -- UEFI console IO, will occur on that
|
||||
# UART; and this DebugLib instance will produce output on a *different* UART.
|
||||
#
|
||||
# This instance is suitable for DXE_RUNTIME_DRIVER modules. When exiting boot
|
||||
# services, UART access is stopped.
|
||||
#
|
||||
# Copyright (C) Red Hat
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 1.27
|
||||
BASE_NAME = DxeRuntimeDebugLibFdtPL011Uart
|
||||
FILE_GUID = 8A6E0972-81B5-4FF4-BB24-A07748415947
|
||||
MODULE_TYPE = DXE_RUNTIME_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = DebugLib|DXE_RUNTIME_DRIVER
|
||||
CONSTRUCTOR = DxeRuntimeDebugLibFdtPL011UartConstructor
|
||||
DESTRUCTOR = DxeRuntimeDebugLibFdtPL011UartDestructor
|
||||
|
||||
[Sources]
|
||||
DebugLib.c
|
||||
Ram.c
|
||||
Ram.h
|
||||
Runtime.c
|
||||
Write.h
|
||||
|
||||
[Packages]
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
ArmVirtPkg/ArmVirtPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
DebugPrintErrorLevelLib
|
||||
HobLib # Ram.c
|
||||
PL011UartLib
|
||||
PcdLib
|
||||
PrintLib
|
||||
|
||||
[Pcd]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue
|
||||
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask
|
||||
gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel
|
||||
|
||||
[FixedPcd]
|
||||
gArmPlatformTokenSpaceGuid.PL011UartClkInHz
|
||||
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
|
||||
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
|
||||
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
|
||||
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
|
||||
|
||||
[Guids]
|
||||
gEarlyPL011BaseAddressGuid # Ram.c
|
107
ArmVirtPkg/Library/DebugLibFdtPL011Uart/Flash.c
Normal file
107
ArmVirtPkg/Library/DebugLibFdtPL011Uart/Flash.c
Normal file
@ -0,0 +1,107 @@
|
||||
/** @file
|
||||
Define DebugLibFdtPL011UartWrite() for modules that may run from flash or RAM.
|
||||
|
||||
Copyright (C) Red Hat
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include <Library/FdtSerialPortAddressLib.h>
|
||||
#include <Library/PL011UartLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
|
||||
#include "Write.h"
|
||||
|
||||
/**
|
||||
(Copied from SerialPortWrite() in "MdePkg/Include/Library/SerialPortLib.h" at
|
||||
commit c4547aefb3d0, with the Buffer non-nullity assertion removed:)
|
||||
|
||||
Write data from buffer to serial device.
|
||||
|
||||
Writes NumberOfBytes data bytes from Buffer to the serial device.
|
||||
The number of bytes actually written to the serial device is returned.
|
||||
If the return value is less than NumberOfBytes, then the write operation failed.
|
||||
If NumberOfBytes is zero, then return 0.
|
||||
|
||||
@param Buffer Pointer to the data buffer to be written.
|
||||
@param NumberOfBytes Number of bytes to written to the serial device.
|
||||
|
||||
@retval 0 NumberOfBytes is 0.
|
||||
@retval >0 The number of bytes written to the serial device.
|
||||
If this value is less than NumberOfBytes, then the write operation failed.
|
||||
**/
|
||||
UINTN
|
||||
DebugLibFdtPL011UartWrite (
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes
|
||||
)
|
||||
{
|
||||
CONST VOID *DeviceTree;
|
||||
RETURN_STATUS Status;
|
||||
FDT_SERIAL_PORTS Ports;
|
||||
UINT64 DebugAddress;
|
||||
UINT64 BaudRate;
|
||||
UINT32 ReceiveFifoDepth;
|
||||
EFI_PARITY_TYPE Parity;
|
||||
UINT8 DataBits;
|
||||
EFI_STOP_BITS_TYPE StopBits;
|
||||
|
||||
DeviceTree = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
|
||||
if (DeviceTree == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Status = FdtSerialGetPorts (DeviceTree, "arm,pl011", &Ports);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Ports.NumberOfPorts == 1) {
|
||||
//
|
||||
// Just one UART; direct DebugLib to it.
|
||||
//
|
||||
DebugAddress = Ports.BaseAddress[0];
|
||||
} else {
|
||||
UINT64 ConsoleAddress;
|
||||
|
||||
Status = FdtSerialGetConsolePort (DeviceTree, &ConsoleAddress);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// At least two UARTs; but failed to get the console preference. Use the
|
||||
// second UART for DebugLib.
|
||||
//
|
||||
DebugAddress = Ports.BaseAddress[1];
|
||||
} else {
|
||||
//
|
||||
// At least two UARTs; and console preference available. Use the first
|
||||
// such UART for DebugLib that *differs* from ConsoleAddress.
|
||||
//
|
||||
if (ConsoleAddress == Ports.BaseAddress[0]) {
|
||||
DebugAddress = Ports.BaseAddress[1];
|
||||
} else {
|
||||
DebugAddress = Ports.BaseAddress[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BaudRate = (UINTN)FixedPcdGet64 (PcdUartDefaultBaudRate);
|
||||
ReceiveFifoDepth = 0; // Use the default value for Fifo depth
|
||||
Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
|
||||
DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
|
||||
StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);
|
||||
|
||||
Status = PL011UartInitializePort (
|
||||
(UINTN)DebugAddress,
|
||||
FixedPcdGet32 (PL011UartClkInHz),
|
||||
&BaudRate,
|
||||
&ReceiveFifoDepth,
|
||||
&Parity,
|
||||
&DataBits,
|
||||
&StopBits
|
||||
);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return PL011UartWrite ((UINTN)DebugAddress, Buffer, NumberOfBytes);
|
||||
}
|
124
ArmVirtPkg/Library/DebugLibFdtPL011Uart/Ram.c
Normal file
124
ArmVirtPkg/Library/DebugLibFdtPL011Uart/Ram.c
Normal file
@ -0,0 +1,124 @@
|
||||
/** @file
|
||||
Define DebugLibFdtPL011UartWrite() for modules that can only run from RAM.
|
||||
|
||||
Copyright (C) Red Hat
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include <Uefi/UefiBaseType.h>
|
||||
#include <Uefi/UefiMultiPhase.h>
|
||||
#include <Pi/PiBootMode.h>
|
||||
#include <Pi/PiHob.h>
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/PL011UartLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Guid/EarlyPL011BaseAddress.h>
|
||||
|
||||
#include "Ram.h"
|
||||
#include "Write.h"
|
||||
|
||||
UINTN mDebugLibFdtPL011UartAddress;
|
||||
RETURN_STATUS mDebugLibFdtPL011UartPermanentStatus = RETURN_SUCCESS;
|
||||
|
||||
/**
|
||||
Statefully initialize both the library instance and the debug PL011 UART.
|
||||
**/
|
||||
STATIC
|
||||
RETURN_STATUS
|
||||
Initialize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
CONST VOID *Hob;
|
||||
CONST EARLY_PL011_BASE_ADDRESS *UartBase;
|
||||
RETURN_STATUS Status;
|
||||
UINTN DebugAddress;
|
||||
UINT64 BaudRate;
|
||||
UINT32 ReceiveFifoDepth;
|
||||
EFI_PARITY_TYPE Parity;
|
||||
UINT8 DataBits;
|
||||
EFI_STOP_BITS_TYPE StopBits;
|
||||
|
||||
if (mDebugLibFdtPL011UartAddress != 0) {
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
if (RETURN_ERROR (mDebugLibFdtPL011UartPermanentStatus)) {
|
||||
return mDebugLibFdtPL011UartPermanentStatus;
|
||||
}
|
||||
|
||||
Hob = GetFirstGuidHob (&gEarlyPL011BaseAddressGuid);
|
||||
if ((Hob == NULL) || (GET_GUID_HOB_DATA_SIZE (Hob) != sizeof *UartBase)) {
|
||||
Status = RETURN_NOT_FOUND;
|
||||
goto Failed;
|
||||
}
|
||||
|
||||
UartBase = GET_GUID_HOB_DATA (Hob);
|
||||
|
||||
DebugAddress = (UINTN)UartBase->DebugAddress;
|
||||
if (DebugAddress == 0) {
|
||||
Status = RETURN_NOT_FOUND;
|
||||
goto Failed;
|
||||
}
|
||||
|
||||
BaudRate = (UINTN)PcdGet64 (PcdUartDefaultBaudRate);
|
||||
ReceiveFifoDepth = 0; // Use the default value for Fifo depth
|
||||
Parity = (EFI_PARITY_TYPE)PcdGet8 (PcdUartDefaultParity);
|
||||
DataBits = PcdGet8 (PcdUartDefaultDataBits);
|
||||
StopBits = (EFI_STOP_BITS_TYPE)PcdGet8 (PcdUartDefaultStopBits);
|
||||
|
||||
Status = PL011UartInitializePort (
|
||||
DebugAddress,
|
||||
FixedPcdGet32 (PL011UartClkInHz),
|
||||
&BaudRate,
|
||||
&ReceiveFifoDepth,
|
||||
&Parity,
|
||||
&DataBits,
|
||||
&StopBits
|
||||
);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
goto Failed;
|
||||
}
|
||||
|
||||
mDebugLibFdtPL011UartAddress = DebugAddress;
|
||||
return RETURN_SUCCESS;
|
||||
|
||||
Failed:
|
||||
mDebugLibFdtPL011UartPermanentStatus = Status;
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
(Copied from SerialPortWrite() in "MdePkg/Include/Library/SerialPortLib.h" at
|
||||
commit c4547aefb3d0, with the Buffer non-nullity assertion removed:)
|
||||
|
||||
Write data from buffer to serial device.
|
||||
|
||||
Writes NumberOfBytes data bytes from Buffer to the serial device.
|
||||
The number of bytes actually written to the serial device is returned.
|
||||
If the return value is less than NumberOfBytes, then the write operation failed.
|
||||
If NumberOfBytes is zero, then return 0.
|
||||
|
||||
@param Buffer Pointer to the data buffer to be written.
|
||||
@param NumberOfBytes Number of bytes to written to the serial device.
|
||||
|
||||
@retval 0 NumberOfBytes is 0.
|
||||
@retval >0 The number of bytes written to the serial device.
|
||||
If this value is less than NumberOfBytes, then the write operation failed.
|
||||
**/
|
||||
UINTN
|
||||
DebugLibFdtPL011UartWrite (
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes
|
||||
)
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
|
||||
Status = Initialize ();
|
||||
if (RETURN_ERROR (Status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return PL011UartWrite (mDebugLibFdtPL011UartAddress, Buffer, NumberOfBytes);
|
||||
}
|
18
ArmVirtPkg/Library/DebugLibFdtPL011Uart/Ram.h
Normal file
18
ArmVirtPkg/Library/DebugLibFdtPL011Uart/Ram.h
Normal file
@ -0,0 +1,18 @@
|
||||
/** @file
|
||||
Declare the variables that modules that can only run from RAM use for
|
||||
remembering initialization status.
|
||||
|
||||
Copyright (C) Red Hat
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#ifndef DEBUG_LIB_FDT_PL011_UART_RAM_H_
|
||||
#define DEBUG_LIB_FDT_PL011_UART_RAM_H_
|
||||
|
||||
#include <Base.h>
|
||||
|
||||
extern UINTN mDebugLibFdtPL011UartAddress;
|
||||
extern RETURN_STATUS mDebugLibFdtPL011UartPermanentStatus;
|
||||
|
||||
#endif
|
27
ArmVirtPkg/Library/DebugLibFdtPL011Uart/RamNonRuntime.c
Normal file
27
ArmVirtPkg/Library/DebugLibFdtPL011Uart/RamNonRuntime.c
Normal file
@ -0,0 +1,27 @@
|
||||
/** @file
|
||||
Provide an empty lib instance constructor for modules that can only run from
|
||||
RAM but are not DXE_RUNTIME_DRIVER modules.
|
||||
|
||||
This ensures that e.g. any HobLib constructor is ordered correctly. (The
|
||||
DXE_CORE calls constructors late, but the DXE_CORE HobLib instance needs no
|
||||
construction anyway.)
|
||||
|
||||
Copyright (C) Red Hat
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include <Base.h>
|
||||
|
||||
/**
|
||||
Empty library instance constructor, only for ensuring the connectivity of the
|
||||
constructor dependency graph.
|
||||
**/
|
||||
RETURN_STATUS
|
||||
EFIAPI
|
||||
DebugLibFdtPL011UartRamConstructor (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return RETURN_SUCCESS;
|
||||
}
|
88
ArmVirtPkg/Library/DebugLibFdtPL011Uart/Runtime.c
Normal file
88
ArmVirtPkg/Library/DebugLibFdtPL011Uart/Runtime.c
Normal file
@ -0,0 +1,88 @@
|
||||
/** @file
|
||||
Permanently disable the library instance in DXE_RUNTIME_DRIVER modules when
|
||||
exiting boot services.
|
||||
|
||||
Copyright (C) Red Hat
|
||||
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include <Uefi/UefiSpec.h>
|
||||
|
||||
#include "Ram.h"
|
||||
|
||||
STATIC EFI_EVENT mExitBootServicesEvent;
|
||||
|
||||
/**
|
||||
Notification function that is triggered when the boot service
|
||||
ExitBootServices() is called.
|
||||
|
||||
@param[in] Event Event whose notification function is being invoked. Here,
|
||||
unused.
|
||||
|
||||
@param[in] Context The pointer to the notification function's context, which
|
||||
is implementation-dependent. Here, unused.
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
ExitBootServicesNotify (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
mDebugLibFdtPL011UartAddress = 0;
|
||||
mDebugLibFdtPL011UartPermanentStatus = RETURN_ABORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Library instance constructor, registering ExitBootServicesNotify().
|
||||
|
||||
@param[in] ImageHandle The firmware-allocated handle for the EFI image.
|
||||
|
||||
@param[in] SystemTable A pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
|
||||
@return Error codes propagated from CreateEvent(); the
|
||||
registration of ExitBootServicesNotify() failed.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DxeRuntimeDebugLibFdtPL011UartConstructor (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
return SystemTable->BootServices->CreateEvent (
|
||||
EVT_SIGNAL_EXIT_BOOT_SERVICES,
|
||||
TPL_CALLBACK,
|
||||
ExitBootServicesNotify,
|
||||
NULL /* NotifyContext */,
|
||||
&mExitBootServicesEvent
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Library instance destructor, deregistering ExitBootServicesNotify().
|
||||
|
||||
@param[in] ImageHandle The firmware-allocated handle for the EFI image.
|
||||
|
||||
@param[in] SystemTable A pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS Library instance tear-down complete.
|
||||
|
||||
@return Error codes propagated from CloseEvent(); the
|
||||
deregistration of ExitBootServicesNotify() failed.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DxeRuntimeDebugLibFdtPL011UartDestructor (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
return SystemTable->BootServices->CloseEvent (mExitBootServicesEvent);
|
||||
}
|
39
ArmVirtPkg/Library/DebugLibFdtPL011Uart/Write.h
Normal file
39
ArmVirtPkg/Library/DebugLibFdtPL011Uart/Write.h
Normal file
@ -0,0 +1,39 @@
|
||||
/** @file
|
||||
Declare DebugLibFdtPL011UartWrite(), for abstracting PL011 UART initialization
|
||||
differences between flash- vs. RAM-based modules.
|
||||
|
||||
Copyright (C) Red Hat
|
||||
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2012 - 2014, ARM Ltd. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#ifndef DEBUG_LIB_FDT_PL011_UART_WRITE_H_
|
||||
#define DEBUG_LIB_FDT_PL011_UART_WRITE_H_
|
||||
|
||||
/**
|
||||
(Copied from SerialPortWrite() in "MdePkg/Include/Library/SerialPortLib.h" at
|
||||
commit c4547aefb3d0, with the Buffer non-nullity assertion removed:)
|
||||
|
||||
Write data from buffer to serial device.
|
||||
|
||||
Writes NumberOfBytes data bytes from Buffer to the serial device.
|
||||
The number of bytes actually written to the serial device is returned.
|
||||
If the return value is less than NumberOfBytes, then the write operation failed.
|
||||
If NumberOfBytes is zero, then return 0.
|
||||
|
||||
@param Buffer Pointer to the data buffer to be written.
|
||||
@param NumberOfBytes Number of bytes to written to the serial device.
|
||||
|
||||
@retval 0 NumberOfBytes is 0.
|
||||
@retval >0 The number of bytes written to the serial device.
|
||||
If this value is less than NumberOfBytes, then the write operation failed.
|
||||
**/
|
||||
UINTN
|
||||
DebugLibFdtPL011UartWrite (
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes
|
||||
);
|
||||
|
||||
#endif
|
@ -17,90 +17,7 @@
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/PlatformHookLib.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
/** Get the UART base address of the console serial-port from the DT.
|
||||
|
||||
This function fetches the node referenced in the "stdout-path"
|
||||
property of the "chosen" node and returns the base address of
|
||||
the console UART.
|
||||
|
||||
@param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
|
||||
@param [out] SerialConsoleAddress If success, contains the base address
|
||||
of the console serial-port.
|
||||
|
||||
@retval EFI_SUCCESS The function completed successfully.
|
||||
@retval EFI_NOT_FOUND Console serial-port info not found in DT.
|
||||
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetSerialConsolePortAddress (
|
||||
IN CONST VOID *Fdt,
|
||||
OUT UINT64 *SerialConsoleAddress
|
||||
)
|
||||
{
|
||||
CONST CHAR8 *Prop;
|
||||
INT32 PropSize;
|
||||
CONST CHAR8 *Path;
|
||||
INT32 PathLen;
|
||||
INT32 ChosenNode;
|
||||
INT32 SerialConsoleNode;
|
||||
INT32 Len;
|
||||
CONST CHAR8 *NodeStatus;
|
||||
CONST UINT64 *RegProperty;
|
||||
|
||||
if ((Fdt == NULL) || (fdt_check_header (Fdt) != 0)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// The "chosen" node resides at the root of the DT. Fetch it.
|
||||
ChosenNode = fdt_path_offset (Fdt, "/chosen");
|
||||
if (ChosenNode < 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
Prop = fdt_getprop (Fdt, ChosenNode, "stdout-path", &PropSize);
|
||||
if (PropSize < 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Determine the actual path length, as a colon terminates the path.
|
||||
Path = ScanMem8 (Prop, PropSize, ':');
|
||||
if (Path == NULL) {
|
||||
PathLen = AsciiStrLen (Prop);
|
||||
} else {
|
||||
PathLen = Path - Prop;
|
||||
}
|
||||
|
||||
// Aliases cannot start with a '/', so it must be the actual path.
|
||||
if (Prop[0] == '/') {
|
||||
SerialConsoleNode = fdt_path_offset_namelen (Fdt, Prop, PathLen);
|
||||
} else {
|
||||
// Lookup the alias, as this contains the actual path.
|
||||
Path = fdt_get_alias_namelen (Fdt, Prop, PathLen);
|
||||
if (Path == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
SerialConsoleNode = fdt_path_offset (Fdt, Path);
|
||||
}
|
||||
|
||||
NodeStatus = fdt_getprop (Fdt, SerialConsoleNode, "status", &Len);
|
||||
if ((NodeStatus != NULL) && (AsciiStrCmp (NodeStatus, "okay") != 0)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
RegProperty = fdt_getprop (Fdt, SerialConsoleNode, "reg", &Len);
|
||||
if (Len != 16) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*SerialConsoleAddress = fdt64_to_cpu (ReadUnaligned64 (RegProperty));
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
#include <Library/FdtSerialPortAddressLib.h>
|
||||
|
||||
/** Platform hook to retrieve the 16550 UART base address from the platform
|
||||
Device tree and store it in PcdSerialRegisterBase.
|
||||
@ -108,6 +25,7 @@ GetSerialConsolePortAddress (
|
||||
@retval RETURN_SUCCESS Success.
|
||||
@retval RETURN_INVALID_PARAMETER A parameter was invalid.
|
||||
@retval RETURN_NOT_FOUND Serial port information not found.
|
||||
@retval RETURN_PROTOCOL_ERROR Invalid information in the Device Tree.
|
||||
|
||||
**/
|
||||
RETURN_STATUS
|
||||
@ -129,7 +47,7 @@ PlatformHookSerialPortInitialize (
|
||||
return RETURN_NOT_FOUND;
|
||||
}
|
||||
|
||||
Status = GetSerialConsolePortAddress (DeviceTreeBase, &SerialConsoleAddress);
|
||||
Status = FdtSerialGetConsolePort (DeviceTreeBase, &SerialConsoleAddress);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
@ -22,12 +22,11 @@
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
PcdLib
|
||||
FdtLib
|
||||
FdtSerialPortAddressLib
|
||||
HobLib
|
||||
|
||||
[Packages]
|
||||
ArmVirtPkg/ArmVirtPkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/PL011UartLib.h>
|
||||
#include <Library/SerialPortLib.h>
|
||||
#include <libfdt.h>
|
||||
#include <Library/FdtSerialPortAddressLib.h>
|
||||
|
||||
RETURN_STATUS
|
||||
EFIAPI
|
||||
@ -56,74 +56,48 @@ SerialPortGetBaseAddress (
|
||||
UINT8 DataBits;
|
||||
EFI_STOP_BITS_TYPE StopBits;
|
||||
VOID *DeviceTreeBase;
|
||||
INT32 Node, Prev;
|
||||
INT32 Len;
|
||||
CONST CHAR8 *Compatible;
|
||||
CONST CHAR8 *NodeStatus;
|
||||
CONST CHAR8 *CompatibleItem;
|
||||
CONST UINT64 *RegProperty;
|
||||
UINTN UartBase;
|
||||
FDT_SERIAL_PORTS Ports;
|
||||
UINT64 UartBase;
|
||||
RETURN_STATUS Status;
|
||||
|
||||
DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
|
||||
|
||||
if ((DeviceTreeBase == NULL) || (fdt_check_header (DeviceTreeBase) != 0)) {
|
||||
if (DeviceTreeBase == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Status = FdtSerialGetPorts (DeviceTreeBase, "arm,pl011", &Ports);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Enumerate all FDT nodes looking for a PL011 and capture its base address
|
||||
// Default to the first port found, but (if there are multiple ports) allow
|
||||
// the "/chosen" node to override it. Note that if FdtSerialGetConsolePort()
|
||||
// fails, it does not modify UartBase.
|
||||
//
|
||||
for (Prev = 0; ; Prev = Node) {
|
||||
Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
|
||||
if (Node < 0) {
|
||||
break;
|
||||
}
|
||||
UartBase = Ports.BaseAddress[0];
|
||||
if (Ports.NumberOfPorts > 1) {
|
||||
FdtSerialGetConsolePort (DeviceTreeBase, &UartBase);
|
||||
}
|
||||
|
||||
Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
|
||||
if (Compatible == NULL) {
|
||||
continue;
|
||||
}
|
||||
BaudRate = (UINTN)FixedPcdGet64 (PcdUartDefaultBaudRate);
|
||||
ReceiveFifoDepth = 0; // Use the default value for Fifo depth
|
||||
Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
|
||||
DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
|
||||
StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);
|
||||
|
||||
//
|
||||
// Iterate over the NULL-separated items in the compatible string
|
||||
//
|
||||
for (CompatibleItem = Compatible; CompatibleItem < Compatible + Len;
|
||||
CompatibleItem += 1 + AsciiStrLen (CompatibleItem))
|
||||
{
|
||||
if (AsciiStrCmp (CompatibleItem, "arm,pl011") == 0) {
|
||||
NodeStatus = fdt_getprop (DeviceTreeBase, Node, "status", &Len);
|
||||
if ((NodeStatus != NULL) && (AsciiStrCmp (NodeStatus, "okay") != 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RegProperty = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
|
||||
if (Len != 16) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
UartBase = (UINTN)fdt64_to_cpu (ReadUnaligned64 (RegProperty));
|
||||
|
||||
BaudRate = (UINTN)FixedPcdGet64 (PcdUartDefaultBaudRate);
|
||||
ReceiveFifoDepth = 0; // Use the default value for Fifo depth
|
||||
Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
|
||||
DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
|
||||
StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);
|
||||
|
||||
Status = PL011UartInitializePort (
|
||||
UartBase,
|
||||
FixedPcdGet32 (PL011UartClkInHz),
|
||||
&BaudRate,
|
||||
&ReceiveFifoDepth,
|
||||
&Parity,
|
||||
&DataBits,
|
||||
&StopBits
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
return UartBase;
|
||||
}
|
||||
}
|
||||
}
|
||||
Status = PL011UartInitializePort (
|
||||
UartBase,
|
||||
FixedPcdGet32 (PL011UartClkInHz),
|
||||
&BaudRate,
|
||||
&ReceiveFifoDepth,
|
||||
&Parity,
|
||||
&DataBits,
|
||||
&StopBits
|
||||
);
|
||||
if (!RETURN_ERROR (Status)) {
|
||||
return UartBase;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -22,11 +22,10 @@
|
||||
[LibraryClasses]
|
||||
PL011UartLib
|
||||
PcdLib
|
||||
FdtLib
|
||||
FdtSerialPortAddressLib
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
ArmVirtPkg/ArmVirtPkg.dec
|
||||
|
||||
|
@ -23,49 +23,57 @@
|
||||
#include <Library/HobLib.h>
|
||||
#include <Guid/EarlyPL011BaseAddress.h>
|
||||
|
||||
STATIC UINTN mSerialBaseAddress;
|
||||
STATIC UINTN mSerialBaseAddress;
|
||||
STATIC RETURN_STATUS mPermanentStatus = RETURN_SUCCESS;
|
||||
|
||||
/**
|
||||
Program hardware of Serial port
|
||||
|
||||
@retval RETURN_SUCCESS If the serial port was initialized successfully by
|
||||
this call, or an earlier call, to
|
||||
SerialPortInitialize().
|
||||
|
||||
@retval RETURN_NOT_FOUND If no PL011 base address could be found.
|
||||
|
||||
@return Error codes forwarded from
|
||||
PL011UartInitializePort().
|
||||
**/
|
||||
RETURN_STATUS
|
||||
EFIAPI
|
||||
SerialPortInitialize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
VOID *Hob;
|
||||
RETURN_STATUS Status;
|
||||
CONST EARLY_PL011_BASE_ADDRESS *UartBase;
|
||||
UINTN SerialBaseAddress;
|
||||
UINT64 BaudRate;
|
||||
UINT32 ReceiveFifoDepth;
|
||||
EFI_PARITY_TYPE Parity;
|
||||
UINT8 DataBits;
|
||||
EFI_STOP_BITS_TYPE StopBits;
|
||||
|
||||
/**
|
||||
if (mSerialBaseAddress != 0) {
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
Program hardware of Serial port
|
||||
|
||||
@return RETURN_NOT_FOUND if no PL011 base address could be found
|
||||
Otherwise, result of PL011UartInitializePort () is returned
|
||||
|
||||
**/
|
||||
RETURN_STATUS
|
||||
EFIAPI
|
||||
FdtPL011SerialPortLibInitialize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
VOID *Hob;
|
||||
CONST UINT64 *UartBase;
|
||||
UINT64 BaudRate;
|
||||
UINT32 ReceiveFifoDepth;
|
||||
EFI_PARITY_TYPE Parity;
|
||||
UINT8 DataBits;
|
||||
EFI_STOP_BITS_TYPE StopBits;
|
||||
if (RETURN_ERROR (mPermanentStatus)) {
|
||||
return mPermanentStatus;
|
||||
}
|
||||
|
||||
Hob = GetFirstGuidHob (&gEarlyPL011BaseAddressGuid);
|
||||
if ((Hob == NULL) || (GET_GUID_HOB_DATA_SIZE (Hob) != sizeof *UartBase)) {
|
||||
return RETURN_NOT_FOUND;
|
||||
Status = RETURN_NOT_FOUND;
|
||||
goto Failed;
|
||||
}
|
||||
|
||||
UartBase = GET_GUID_HOB_DATA (Hob);
|
||||
|
||||
mSerialBaseAddress = (UINTN)*UartBase;
|
||||
if (mSerialBaseAddress == 0) {
|
||||
return RETURN_NOT_FOUND;
|
||||
SerialBaseAddress = (UINTN)UartBase->ConsoleAddress;
|
||||
if (SerialBaseAddress == 0) {
|
||||
Status = RETURN_NOT_FOUND;
|
||||
goto Failed;
|
||||
}
|
||||
|
||||
BaudRate = (UINTN)PcdGet64 (PcdUartDefaultBaudRate);
|
||||
@ -74,15 +82,25 @@ FdtPL011SerialPortLibInitialize (
|
||||
DataBits = PcdGet8 (PcdUartDefaultDataBits);
|
||||
StopBits = (EFI_STOP_BITS_TYPE)PcdGet8 (PcdUartDefaultStopBits);
|
||||
|
||||
return PL011UartInitializePort (
|
||||
mSerialBaseAddress,
|
||||
FixedPcdGet32 (PL011UartClkInHz),
|
||||
&BaudRate,
|
||||
&ReceiveFifoDepth,
|
||||
&Parity,
|
||||
&DataBits,
|
||||
&StopBits
|
||||
);
|
||||
Status = PL011UartInitializePort (
|
||||
SerialBaseAddress,
|
||||
FixedPcdGet32 (PL011UartClkInHz),
|
||||
&BaudRate,
|
||||
&ReceiveFifoDepth,
|
||||
&Parity,
|
||||
&DataBits,
|
||||
&StopBits
|
||||
);
|
||||
if (RETURN_ERROR (Status)) {
|
||||
goto Failed;
|
||||
}
|
||||
|
||||
mSerialBaseAddress = SerialBaseAddress;
|
||||
return RETURN_SUCCESS;
|
||||
|
||||
Failed:
|
||||
mPermanentStatus = Status;
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,7 +120,7 @@ SerialPortWrite (
|
||||
IN UINTN NumberOfBytes
|
||||
)
|
||||
{
|
||||
if (mSerialBaseAddress != 0) {
|
||||
if (!RETURN_ERROR (SerialPortInitialize ())) {
|
||||
return PL011UartWrite (mSerialBaseAddress, Buffer, NumberOfBytes);
|
||||
}
|
||||
|
||||
@ -126,7 +144,7 @@ SerialPortRead (
|
||||
IN UINTN NumberOfBytes
|
||||
)
|
||||
{
|
||||
if (mSerialBaseAddress != 0) {
|
||||
if (!RETURN_ERROR (SerialPortInitialize ())) {
|
||||
return PL011UartRead (mSerialBaseAddress, Buffer, NumberOfBytes);
|
||||
}
|
||||
|
||||
@ -146,7 +164,7 @@ SerialPortPoll (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (mSerialBaseAddress != 0) {
|
||||
if (!RETURN_ERROR (SerialPortInitialize ())) {
|
||||
return PL011UartPoll (mSerialBaseAddress);
|
||||
}
|
||||
|
||||
@ -199,7 +217,7 @@ SerialPortSetAttributes (
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
|
||||
if (mSerialBaseAddress == 0) {
|
||||
if (RETURN_ERROR (SerialPortInitialize ())) {
|
||||
Status = RETURN_UNSUPPORTED;
|
||||
} else {
|
||||
Status = PL011UartInitializePort (
|
||||
@ -234,7 +252,7 @@ SerialPortSetControl (
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
|
||||
if (mSerialBaseAddress == 0) {
|
||||
if (RETURN_ERROR (SerialPortInitialize ())) {
|
||||
Status = RETURN_UNSUPPORTED;
|
||||
} else {
|
||||
Status = PL011UartSetControl (mSerialBaseAddress, Control);
|
||||
@ -261,7 +279,7 @@ SerialPortGetControl (
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
|
||||
if (mSerialBaseAddress == 0) {
|
||||
if (RETURN_ERROR (SerialPortInitialize ())) {
|
||||
Status = RETURN_UNSUPPORTED;
|
||||
} else {
|
||||
Status = PL011UartGetControl (mSerialBaseAddress, Control);
|
||||
|
@ -15,7 +15,7 @@
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = SerialPortLib|DXE_CORE DXE_DRIVER UEFI_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION
|
||||
CONSTRUCTOR = FdtPL011SerialPortLibInitialize
|
||||
CONSTRUCTOR = SerialPortInitialize
|
||||
|
||||
[Sources.common]
|
||||
FdtPL011SerialPortLib.c
|
||||
|
@ -0,0 +1,256 @@
|
||||
/** @file
|
||||
Determine the base addresses of serial ports from the Device Tree.
|
||||
|
||||
Copyright (C) Red Hat
|
||||
Copyright (c) 2011 - 2023, Arm Ltd. All rights reserved.<BR>
|
||||
Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
|
||||
Copyright (c) 2014 - 2020, Linaro Ltd. All rights reserved.<BR>
|
||||
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/FdtSerialPortAddressLib.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
/**
|
||||
Read the "reg" property of Node in DeviceTree as a UINT64 base address.
|
||||
|
||||
@param[in] DeviceTree The flat device tree (FDT) to scan.
|
||||
|
||||
@param[in] Node The node to read the "reg" property of.
|
||||
|
||||
@param[out] BaseAddress On success, the base address read out of Node's "reg"
|
||||
property. On error, not modified.
|
||||
|
||||
@retval RETURN_DEVICE_ERROR Node has a "status" property with value
|
||||
different from "okay".
|
||||
|
||||
@retval RETURN_NOT_FOUND Node does not have a "reg" property.
|
||||
|
||||
@retval RETURN_BAD_BUFFER_SIZE The size of Node's "reg" property is not 16
|
||||
bytes.
|
||||
|
||||
@retval RETURN_SUCCESS BaseAddress has been populated.
|
||||
**/
|
||||
STATIC
|
||||
RETURN_STATUS
|
||||
GetBaseAddress (
|
||||
IN CONST VOID *DeviceTree,
|
||||
IN INT32 Node,
|
||||
OUT UINT64 *BaseAddress
|
||||
)
|
||||
{
|
||||
CONST CHAR8 *NodeStatus;
|
||||
CONST VOID *RegProp;
|
||||
INT32 PropSize;
|
||||
|
||||
NodeStatus = fdt_getprop (DeviceTree, Node, "status", NULL);
|
||||
if ((NodeStatus != NULL) && (AsciiStrCmp (NodeStatus, "okay") != 0)) {
|
||||
return RETURN_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
RegProp = fdt_getprop (DeviceTree, Node, "reg", &PropSize);
|
||||
if (RegProp == NULL) {
|
||||
return RETURN_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (PropSize != 16) {
|
||||
return RETURN_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
*BaseAddress = fdt64_to_cpu (ReadUnaligned64 (RegProp));
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Collect the first ARRAY_SIZE (Ports->BaseAddress) serial ports into Ports from
|
||||
DeviceTree.
|
||||
|
||||
@param[in] DeviceTree The flat device tree (FDT) to scan.
|
||||
|
||||
@param[in] Compatible Look for Compatible in the "compatible" property of the
|
||||
scanned nodes.
|
||||
|
||||
@param[out] Ports On successful return, Ports->NumberOfPorts contains the
|
||||
number of serial ports found; it is (a) positive and
|
||||
(b) at most ARRAY_SIZE (Ports->BaseAddress). If the FDT
|
||||
had more serial ports, those are not reported. On
|
||||
error, the contents of Ports are indeterminate.
|
||||
|
||||
@retval RETURN_INVALID_PARAMETER DeviceTree does not point to a valid FDT
|
||||
header.
|
||||
|
||||
@retval RETURN_NOT_FOUND No compatible and enabled serial port has
|
||||
been found.
|
||||
|
||||
@retval RETURN_SUCCESS At least one compatible and enabled serial
|
||||
port has been found; Ports has been filled
|
||||
in.
|
||||
**/
|
||||
RETURN_STATUS
|
||||
EFIAPI
|
||||
FdtSerialGetPorts (
|
||||
IN CONST VOID *DeviceTree,
|
||||
IN CONST CHAR8 *Compatible,
|
||||
OUT FDT_SERIAL_PORTS *Ports
|
||||
)
|
||||
{
|
||||
INT32 Node;
|
||||
|
||||
if (fdt_check_header (DeviceTree) != 0) {
|
||||
return RETURN_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Ports->NumberOfPorts = 0;
|
||||
Node = fdt_next_node (DeviceTree, 0, NULL);
|
||||
while ((Node > 0) &&
|
||||
(Ports->NumberOfPorts < ARRAY_SIZE (Ports->BaseAddress)))
|
||||
{
|
||||
CONST CHAR8 *CompatProp;
|
||||
INT32 PropSize;
|
||||
|
||||
CompatProp = fdt_getprop (DeviceTree, Node, "compatible", &PropSize);
|
||||
if (CompatProp != NULL) {
|
||||
CONST CHAR8 *CompatItem;
|
||||
|
||||
CompatItem = CompatProp;
|
||||
while ((CompatItem < CompatProp + PropSize) &&
|
||||
(AsciiStrCmp (CompatItem, Compatible) != 0))
|
||||
{
|
||||
CompatItem += AsciiStrLen (CompatItem) + 1;
|
||||
}
|
||||
|
||||
if (CompatItem < CompatProp + PropSize) {
|
||||
RETURN_STATUS Status;
|
||||
UINT64 BaseAddress;
|
||||
|
||||
Status = GetBaseAddress (DeviceTree, Node, &BaseAddress);
|
||||
if (!RETURN_ERROR (Status)) {
|
||||
Ports->BaseAddress[Ports->NumberOfPorts++] = BaseAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Node = fdt_next_node (DeviceTree, Node, NULL);
|
||||
}
|
||||
|
||||
return Ports->NumberOfPorts > 0 ? RETURN_SUCCESS : RETURN_NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
Fetch the base address of the serial port identified in the "stdout-path"
|
||||
property of the "/chosen" node in DeviceTree.
|
||||
|
||||
@param[in] DeviceTree The flat device tree (FDT) to scan.
|
||||
|
||||
@param[out] BaseAddress On success, the base address of the preferred serial
|
||||
port (to be used as console). On error, BaseAddress
|
||||
is not modified.
|
||||
|
||||
@retval RETURN_INVALID_PARAMETER DeviceTree does not point to a valid FDT
|
||||
header.
|
||||
|
||||
@retval RETURN_NOT_FOUND No enabled console port has been found.
|
||||
|
||||
@retval RETURN_PROTOCOL_ERROR The first (or only) node path in the
|
||||
"stdout-path" property is an empty string.
|
||||
|
||||
@retval RETURN_PROTOCOL_ERROR The console port has been found in the FDT,
|
||||
but its base address is not correctly
|
||||
represented.
|
||||
|
||||
@retval RETURN_SUCCESS BaseAddress has been populated.
|
||||
**/
|
||||
RETURN_STATUS
|
||||
EFIAPI
|
||||
FdtSerialGetConsolePort (
|
||||
IN CONST VOID *DeviceTree,
|
||||
OUT UINT64 *BaseAddress
|
||||
)
|
||||
{
|
||||
INT32 ChosenNode;
|
||||
CONST CHAR8 *StdoutPathProp;
|
||||
INT32 PropSize;
|
||||
CONST CHAR8 *StdoutPathEnd;
|
||||
UINTN StdoutPathLength;
|
||||
INT32 ConsoleNode;
|
||||
RETURN_STATUS Status;
|
||||
|
||||
if (fdt_check_header (DeviceTree) != 0) {
|
||||
return RETURN_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ChosenNode = fdt_path_offset (DeviceTree, "/chosen");
|
||||
if (ChosenNode < 0) {
|
||||
return RETURN_NOT_FOUND;
|
||||
}
|
||||
|
||||
StdoutPathProp = fdt_getprop (
|
||||
DeviceTree,
|
||||
ChosenNode,
|
||||
"stdout-path",
|
||||
&PropSize
|
||||
);
|
||||
if (StdoutPathProp == NULL) {
|
||||
return RETURN_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// If StdoutPathProp contains a colon (":"), then the colon terminates the
|
||||
// path we're interested in.
|
||||
//
|
||||
StdoutPathEnd = AsciiStrStr (StdoutPathProp, ":");
|
||||
if (StdoutPathEnd == NULL) {
|
||||
StdoutPathLength = PropSize - 1;
|
||||
} else {
|
||||
StdoutPathLength = StdoutPathEnd - StdoutPathProp;
|
||||
}
|
||||
|
||||
if (StdoutPathLength == 0) {
|
||||
return RETURN_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
if (StdoutPathProp[0] == '/') {
|
||||
//
|
||||
// StdoutPathProp starts with an absolute node path.
|
||||
//
|
||||
ConsoleNode = fdt_path_offset_namelen (
|
||||
DeviceTree,
|
||||
StdoutPathProp,
|
||||
(INT32)StdoutPathLength
|
||||
);
|
||||
} else {
|
||||
//
|
||||
// StdoutPathProp starts with an alias.
|
||||
//
|
||||
CONST CHAR8 *ResolvedStdoutPath;
|
||||
|
||||
ResolvedStdoutPath = fdt_get_alias_namelen (
|
||||
DeviceTree,
|
||||
StdoutPathProp,
|
||||
(INT32)StdoutPathLength
|
||||
);
|
||||
if (ResolvedStdoutPath == NULL) {
|
||||
return RETURN_NOT_FOUND;
|
||||
}
|
||||
|
||||
ConsoleNode = fdt_path_offset (DeviceTree, ResolvedStdoutPath);
|
||||
}
|
||||
|
||||
if (ConsoleNode < 0) {
|
||||
return RETURN_NOT_FOUND;
|
||||
}
|
||||
|
||||
Status = GetBaseAddress (DeviceTree, ConsoleNode, BaseAddress);
|
||||
switch (Status) {
|
||||
case RETURN_NOT_FOUND:
|
||||
case RETURN_BAD_BUFFER_SIZE:
|
||||
return RETURN_PROTOCOL_ERROR;
|
||||
case RETURN_SUCCESS:
|
||||
return RETURN_SUCCESS;
|
||||
default:
|
||||
return RETURN_NOT_FOUND;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
## @file
|
||||
# Determine the base addresses of serial ports from the Device Tree.
|
||||
#
|
||||
# Copyright (C) Red Hat
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 1.27
|
||||
BASE_NAME = FdtSerialPortAddressLib
|
||||
FILE_GUID = AEBE813B-25EA-40E5-95C4-2B864FE1E951
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = FdtSerialPortAddressLib
|
||||
|
||||
[Sources]
|
||||
FdtSerialPortAddressLib.c
|
||||
|
||||
[Packages]
|
||||
ArmVirtPkg/ArmVirtPkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
FdtLib
|
@ -606,7 +606,7 @@ SetupVirtioSerial (
|
||||
1
|
||||
};
|
||||
|
||||
STATIC CONST VENDOR_DEVICE_PATH TerminalNode = {
|
||||
STATIC VENDOR_DEVICE_PATH TerminalNode = {
|
||||
{
|
||||
MESSAGING_DEVICE_PATH,
|
||||
MSG_VENDOR_DP,
|
||||
@ -615,7 +615,7 @@ SetupVirtioSerial (
|
||||
(UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
|
||||
},
|
||||
},
|
||||
DEVICE_PATH_MESSAGING_VT_UTF8
|
||||
// copy from PcdTerminalTypeGuidBuffer
|
||||
};
|
||||
|
||||
EFI_STATUS Status;
|
||||
@ -634,6 +634,11 @@ SetupVirtioSerial (
|
||||
return;
|
||||
}
|
||||
|
||||
CopyGuid (
|
||||
&TerminalNode.Guid,
|
||||
PcdGetPtr (PcdTerminalTypeGuidBuffer)
|
||||
);
|
||||
|
||||
DevicePath = AppendDevicePathNode (
|
||||
DevicePath,
|
||||
&SerialNode.Header
|
||||
|
@ -9,11 +9,13 @@
|
||||
|
||||
#include <PiPei.h>
|
||||
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/PeiServicesLib.h>
|
||||
#include <Library/FdtSerialPortAddressLib.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <Guid/EarlyPL011BaseAddress.h>
|
||||
@ -37,25 +39,23 @@ PlatformPeim (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
VOID *Base;
|
||||
VOID *NewBase;
|
||||
UINTN FdtSize;
|
||||
UINTN FdtPages;
|
||||
UINT64 *FdtHobData;
|
||||
UINT64 *UartHobData;
|
||||
INT32 Node, Prev;
|
||||
INT32 Parent, Depth;
|
||||
CONST CHAR8 *Compatible;
|
||||
CONST CHAR8 *CompItem;
|
||||
CONST CHAR8 *NodeStatus;
|
||||
INT32 Len;
|
||||
INT32 RangesLen;
|
||||
INT32 StatusLen;
|
||||
CONST UINT64 *RegProp;
|
||||
CONST UINT32 *RangesProp;
|
||||
UINT64 UartBase;
|
||||
UINT64 TpmBase;
|
||||
EFI_STATUS Status;
|
||||
VOID *Base;
|
||||
VOID *NewBase;
|
||||
UINTN FdtSize;
|
||||
UINTN FdtPages;
|
||||
UINT64 *FdtHobData;
|
||||
EARLY_PL011_BASE_ADDRESS *UartHobData;
|
||||
FDT_SERIAL_PORTS Ports;
|
||||
INT32 Node, Prev;
|
||||
INT32 Parent, Depth;
|
||||
CONST CHAR8 *Compatible;
|
||||
CONST CHAR8 *CompItem;
|
||||
INT32 Len;
|
||||
INT32 RangesLen;
|
||||
CONST UINT64 *RegProp;
|
||||
CONST UINT32 *RangesProp;
|
||||
UINT64 TpmBase;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Base = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
|
||||
ASSERT (Base != NULL);
|
||||
@ -73,7 +73,56 @@ PlatformPeim (
|
||||
|
||||
UartHobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *UartHobData);
|
||||
ASSERT (UartHobData != NULL);
|
||||
*UartHobData = 0;
|
||||
SetMem (UartHobData, sizeof *UartHobData, 0);
|
||||
|
||||
Status = FdtSerialGetPorts (Base, "arm,pl011", &Ports);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
if (Ports.NumberOfPorts == 1) {
|
||||
//
|
||||
// Just one UART; direct both SerialPortLib+console and DebugLib to it.
|
||||
//
|
||||
UartHobData->ConsoleAddress = Ports.BaseAddress[0];
|
||||
UartHobData->DebugAddress = Ports.BaseAddress[0];
|
||||
} else {
|
||||
UINT64 ConsoleAddress;
|
||||
|
||||
Status = FdtSerialGetConsolePort (Base, &ConsoleAddress);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// At least two UARTs; but failed to get the console preference. Use the
|
||||
// first UART for SerialPortLib+console, and the second one for
|
||||
// DebugLib.
|
||||
//
|
||||
UartHobData->ConsoleAddress = Ports.BaseAddress[0];
|
||||
UartHobData->DebugAddress = Ports.BaseAddress[1];
|
||||
} else {
|
||||
//
|
||||
// At least two UARTs; and console preference available. Use the
|
||||
// preferred UART for SerialPortLib+console, and *another* UART for
|
||||
// DebugLib.
|
||||
//
|
||||
UartHobData->ConsoleAddress = ConsoleAddress;
|
||||
if (ConsoleAddress == Ports.BaseAddress[0]) {
|
||||
UartHobData->DebugAddress = Ports.BaseAddress[1];
|
||||
} else {
|
||||
UartHobData->DebugAddress = Ports.BaseAddress[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"%a: PL011 UART (console) @ 0x%lx\n",
|
||||
__func__,
|
||||
UartHobData->ConsoleAddress
|
||||
));
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"%a: PL011 UART (debug) @ 0x%lx\n",
|
||||
__func__,
|
||||
UartHobData->DebugAddress
|
||||
));
|
||||
}
|
||||
|
||||
TpmBase = 0;
|
||||
|
||||
@ -100,23 +149,8 @@ PlatformPeim (
|
||||
for (CompItem = Compatible; CompItem != NULL && CompItem < Compatible + Len;
|
||||
CompItem += 1 + AsciiStrLen (CompItem))
|
||||
{
|
||||
if (AsciiStrCmp (CompItem, "arm,pl011") == 0) {
|
||||
NodeStatus = fdt_getprop (Base, Node, "status", &StatusLen);
|
||||
if ((NodeStatus != NULL) && (AsciiStrCmp (NodeStatus, "okay") != 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RegProp = fdt_getprop (Base, Node, "reg", &Len);
|
||||
ASSERT (Len == 16);
|
||||
|
||||
UartBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a: PL011 UART @ 0x%lx\n", __func__, UartBase));
|
||||
|
||||
*UartHobData = UartBase;
|
||||
break;
|
||||
} else if (FeaturePcdGet (PcdTpm2SupportEnabled) &&
|
||||
(AsciiStrCmp (CompItem, "tcg,tpm-tis-mmio") == 0))
|
||||
if (FeaturePcdGet (PcdTpm2SupportEnabled) &&
|
||||
(AsciiStrCmp (CompItem, "tcg,tpm-tis-mmio") == 0))
|
||||
{
|
||||
RegProp = fdt_getprop (Base, Node, "reg", &Len);
|
||||
ASSERT (Len == 8 || Len == 16);
|
||||
|
@ -31,9 +31,11 @@
|
||||
gArmVirtTokenSpaceGuid.PcdTpm2SupportEnabled
|
||||
|
||||
[LibraryClasses]
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
HobLib
|
||||
FdtLib
|
||||
FdtSerialPortAddressLib
|
||||
PcdLib
|
||||
PeiServicesLib
|
||||
|
||||
|
@ -244,6 +244,11 @@ class PlatformBuilder(UefiBuilder, BuildSettingsManager):
|
||||
# Conditional Args
|
||||
if (self.env.GetValue("QEMU_HEADLESS").upper() == "TRUE"):
|
||||
args += " -display none" # no graphics
|
||||
else:
|
||||
args += " -device virtio-gpu-pci" # add recommended QEMU graphics device
|
||||
args += " -device qemu-xhci,id=usb" # add USB support for below devices
|
||||
args += " -device usb-tablet,id=input0,bus=usb.0,port=1" # add a usb mouse
|
||||
args += " -device usb-kbd,id=input1,bus=usb.0,port=2" # add a usb keyboard
|
||||
|
||||
if (self.env.GetValue("MAKE_STARTUP_NSH").upper() == "TRUE"):
|
||||
f = open(os.path.join(VirtualDrive, "startup.nsh"), "w")
|
||||
|
@ -5,28 +5,43 @@ to use the same Pytools based build infrastructure locally.
|
||||
|
||||
## Supported Configuration Details
|
||||
|
||||
This solution for building and running ArmVirtPkg has only been validated with Ubuntu
|
||||
18.04 and the GCC5 toolchain. Two different firmware builds are supported and are
|
||||
described below.
|
||||
This solution for building and running ArmVirtPkg has been validated with Fedora
|
||||
37 Linux and the GCC5 toolchain. The following different firmware builds are
|
||||
supported.
|
||||
|
||||
| Configuration name | Architecture | DSC File |Additional Flags |
|
||||
| :---------- | :----- | :----- | :---- |
|
||||
| AARCH64 | AARCH64 | ArmVirtQemu.dsc | None |
|
||||
| ARM | ARM | ArmVirtQemu.dsc | None |
|
||||
| Configuration name | Architecture | DSC File | Additional Flags |
|
||||
| :---------- | :----- | :----- | :---- |
|
||||
| AARCH64 - KVM Cloud HV | AARCH64 | ArmVirtCloudHv.dsc | None |
|
||||
| ARM - KVM Cloud HV | ARM | ArmVirtCloudHv.dsc | None |
|
||||
| AARCH64 - kvmtool | AARCH64 | ArmVirtKvmTool.dsc | None |
|
||||
| ARM - kvmtool | ARM | ArmVirtKvmTool.dsc | None |
|
||||
| AARCH64 - QEMU | AARCH64 | ArmVirtQemu.dsc | None |
|
||||
| ARM - QEMU | ARM | ArmVirtQemu.dsc | None |
|
||||
| AARCH64 - QEMU Kernel | AARCH64 | ArmVirtQemuKernel.dsc | None |
|
||||
| ARM - QEMU Kernel | ARM | ArmVirtQemuKernel.dsc | None |
|
||||
| AARCH64 - Xen HV | AARCH64 | ArmVirtXen.dsc | None |
|
||||
| ARM - Xen HV | ARM | ArmVirtXen.dsc | None |
|
||||
|
||||
## EDK2 Developer environment
|
||||
|
||||
- [Python 3.8.x - Download & Install](https://www.python.org/downloads/)
|
||||
- [Python 3.12.x - Download & Install](https://www.python.org/downloads/)
|
||||
- [GIT - Download & Install](https://git-scm.com/download/)
|
||||
- [QEMU - Download, Install, and add to your path](https://www.qemu.org/download/)
|
||||
- [Edk2 Source](https://github.com/tianocore/edk2)
|
||||
- Additional packages found necessary for Ubuntu 18.04
|
||||
- apt-get install gcc g++ make uuid-dev
|
||||
- Additional packages found necessary for Fedora Linux 37
|
||||
- dnf install gcc g++ make libuuid-devel
|
||||
|
||||
Note: edksetup, Submodule initialization and manual installation of NASM, iASL, or
|
||||
the required cross-compiler toolchains are **not** required, this is handled by the
|
||||
Pytools build system.
|
||||
|
||||
The code is built in CI using a container. The latest Fedora Linux 37 container is
|
||||
available in this GitHub container registry feed
|
||||
[fedora-37-test](https://github.com/tianocore/containers/pkgs/container/containers%2Ffedora-37-test).
|
||||
|
||||
The exact container version tested in CI is maintained in this file
|
||||
[edk2/.azurepipelines/templates/default.yml](https://github.com/tianocore/edk2/blob/HEAD/.azurepipelines/templates/defaults.yml).
|
||||
|
||||
## Building with Pytools for ArmVirtPkg
|
||||
|
||||
If you are unfamiliar with Pytools, it is recommended to first read through
|
||||
@ -57,16 +72,16 @@ the generic set of edk2 [Build Instructions](https://github.com/tianocore/tianoc
|
||||
pip install --upgrade -r pip-requirements.txt
|
||||
```
|
||||
|
||||
4. Initialize & Update Submodules - only when submodules updated
|
||||
4. Initialize & Update Submodules - only when submodules updated (QEMU build example)
|
||||
|
||||
``` bash
|
||||
stuart_setup -c ArmVirtPkg/PlatformCI/PlatformBuild.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH>
|
||||
stuart_setup -c ArmVirtPkg/PlatformCI/QemuBuild.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH>
|
||||
```
|
||||
|
||||
5. Initialize & Update Dependencies - only as needed when ext_deps change
|
||||
5. Initialize & Update Dependencies - only as needed when ext_deps change (QEMU build example)
|
||||
|
||||
``` bash
|
||||
stuart_update -c ArmVirtPkg/PlatformCI/PlatformBuild.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH>
|
||||
stuart_update -c ArmVirtPkg/PlatformCI/QemuBuild.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH>
|
||||
```
|
||||
|
||||
6. Compile the basetools if necessary - only when basetools C source files change
|
||||
@ -75,13 +90,13 @@ the generic set of edk2 [Build Instructions](https://github.com/tianocore/tianoc
|
||||
python BaseTools/Edk2ToolsBuild.py -t <ToolChainTag>
|
||||
```
|
||||
|
||||
7. Compile Firmware
|
||||
7. Compile Firmware (QEMU build example)
|
||||
|
||||
``` bash
|
||||
stuart_build -c ArmVirtPkg/PlatformCI/PlatformBuild.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH>
|
||||
stuart_build -c ArmVirtPkg/PlatformCI/QemuBuild.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH>
|
||||
```
|
||||
|
||||
- use `stuart_build -c ArmVirtPkg/PlatformCI/PlatformBuild.py -h` option to see additional
|
||||
- use `stuart_build -c ArmVirtPkg/PlatformCI/QemuBuild.py -h` option to see additional
|
||||
options like `--clean`
|
||||
|
||||
8. Running Emulator
|
||||
@ -90,7 +105,7 @@ the generic set of edk2 [Build Instructions](https://github.com/tianocore/tianoc
|
||||
- or use the `--FlashOnly` feature to just run the emulator.
|
||||
|
||||
``` bash
|
||||
stuart_build -c ArmVirtPkg/PlatformCI/PlatformBuild.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH> --FlashOnly
|
||||
stuart_build -c ArmVirtPkg/PlatformCI/QemuBuild.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH> --FlashOnly
|
||||
```
|
||||
|
||||
### Notes
|
||||
@ -120,7 +135,7 @@ command-line. _stuart_build_ currently requires values to be assigned, so add an
|
||||
For example, to enable the TPM2 support, instead of the traditional "-D TPM2_ENABLE=TRUE", the stuart_build
|
||||
command-line would be:
|
||||
|
||||
`stuart_build -c ArmVirtPkg/PlatformCI/PlatformBuild.py BLD_*_TPM2_ENABLE=TRUE`
|
||||
`stuart_build -c ArmVirtPkg/PlatformCI/QemuBuild.py BLD_*_TPM2_ENABLE=TRUE`
|
||||
|
||||
## References
|
||||
|
||||
|
@ -1859,7 +1859,7 @@ DEFINE CLANGDWARF_X64_DLINK2_FLAGS = -Wl,--defsym=PECOFF_HEADER_SIZE=0x22
|
||||
DEFINE CLANGDWARF_IA32_TARGET = -target i686-pc-linux-gnu
|
||||
DEFINE CLANGDWARF_X64_TARGET = -target x86_64-pc-linux-gnu
|
||||
|
||||
DEFINE CLANGDWARF_WARNING_OVERRIDES = -Wno-parentheses-equality -Wno-tautological-compare -Wno-tautological-constant-out-of-range-compare -Wno-empty-body -Wno-unused-const-variable -Wno-varargs -Wno-unknown-warning-option -Wno-unused-but-set-variable -Wno-unused-const-variable -Wno-unaligned-access -Wno-unneeded-internal-declaration
|
||||
DEFINE CLANGDWARF_WARNING_OVERRIDES = -Wno-parentheses-equality -Wno-empty-body -Wno-unused-const-variable -Wno-varargs -Wno-unknown-warning-option -Wno-unused-but-set-variable -Wno-unused-const-variable -Wno-unaligned-access -Wno-unneeded-internal-declaration
|
||||
DEFINE CLANGDWARF_ALL_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) DEF(CLANGDWARF_WARNING_OVERRIDES) -fno-stack-protector -mms-bitfields -Wno-address -Wno-shift-negative-value -Wno-unknown-pragmas -Wno-incompatible-library-redeclaration -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -msoft-float -mno-implicit-float -ftrap-function=undefined_behavior_has_been_optimized_away_by_clang -funsigned-char -fno-ms-extensions -Wno-null-dereference
|
||||
|
||||
###########################
|
||||
@ -2015,7 +2015,7 @@ DEFINE CLANGDWARF_AARCH64_DLINK_FLAGS = DEF(CLANGDWARF_AARCH64_TARGET) DEF(GCC_
|
||||
*_CLANGDWARF_AARCH64_RC_FLAGS = DEF(GCC_AARCH64_RC_FLAGS) DEF(GCC_AARCH64_RC_BTI_FLAGS)
|
||||
*_CLANGDWARF_AARCH64_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS) DEF(CLANGDWARF_AARCH64_TARGET) $(PLATFORM_FLAGS)
|
||||
*_CLANGDWARF_AARCH64_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS) DEF(CLANGDWARF_AARCH64_TARGET)
|
||||
*_CLANGDWARF_AARCH64_CC_XIPFLAGS = DEF(GCC_AARCH64_CC_XIPFLAGS)
|
||||
*_CLANGDWARF_AARCH64_CC_XIPFLAGS = -mstrict-align
|
||||
|
||||
DEBUG_CLANGDWARF_AARCH64_CC_FLAGS = DEF(CLANGDWARF_AARCH64_CC_FLAGS) $(PLATFORM_FLAGS) -flto -O1
|
||||
DEBUG_CLANGDWARF_AARCH64_DLINK_FLAGS = DEF(CLANGDWARF_AARCH64_DLINK_FLAGS) -flto -Wl,-O1 -fuse-ld=lld -L$(WORKSPACE)/ArmPkg/Library/GccLto -llto-aarch64 -Wl,-plugin-opt=-pass-through=-llto-aarch64 -Wl,--no-pie,--no-relax
|
||||
|
222
BaseTools/Plugin/CodeQL/CodeQlAnalyzePlugin.py
Normal file
222
BaseTools/Plugin/CodeQL/CodeQlAnalyzePlugin.py
Normal file
@ -0,0 +1,222 @@
|
||||
# @file CodeQAnalyzePlugin.py
|
||||
#
|
||||
# A build plugin that analyzes a CodeQL database.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import yaml
|
||||
|
||||
from analyze import analyze_filter
|
||||
from common import codeql_plugin
|
||||
|
||||
from edk2toolext import edk2_logging
|
||||
from edk2toolext.environment.plugintypes.uefi_build_plugin import \
|
||||
IUefiBuildPlugin
|
||||
from edk2toolext.environment.uefi_build import UefiBuilder
|
||||
from edk2toollib.uefi.edk2.path_utilities import Edk2Path
|
||||
from edk2toollib.utility_functions import RunCmd
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class CodeQlAnalyzePlugin(IUefiBuildPlugin):
|
||||
|
||||
def do_post_build(self, builder: UefiBuilder) -> int:
|
||||
"""CodeQL analysis post-build functionality.
|
||||
|
||||
Args:
|
||||
builder (UefiBuilder): A UEFI builder object for this build.
|
||||
|
||||
Returns:
|
||||
int: The number of CodeQL errors found. Zero indicates that
|
||||
AuditOnly mode is enabled or no failures were found.
|
||||
"""
|
||||
self.builder = builder
|
||||
self.package = builder.edk2path.GetContainingPackage(
|
||||
builder.edk2path.GetAbsolutePathOnThisSystemFromEdk2RelativePath(
|
||||
builder.env.GetValue("ACTIVE_PLATFORM")
|
||||
)
|
||||
)
|
||||
|
||||
self.package_path = Path(
|
||||
builder.edk2path.GetAbsolutePathOnThisSystemFromEdk2RelativePath(
|
||||
self.package
|
||||
)
|
||||
)
|
||||
self.target = builder.env.GetValue("TARGET")
|
||||
|
||||
self.codeql_db_path = codeql_plugin.get_codeql_db_path(
|
||||
builder.ws, self.package, self.target,
|
||||
new_path=False)
|
||||
|
||||
self.codeql_path = codeql_plugin.get_codeql_cli_path()
|
||||
if not self.codeql_path:
|
||||
logging.critical("CodeQL build enabled but CodeQL CLI application "
|
||||
"not found.")
|
||||
return -1
|
||||
|
||||
codeql_sarif_dir_path = self.codeql_db_path[
|
||||
:self.codeql_db_path.rindex('-')]
|
||||
codeql_sarif_dir_path = codeql_sarif_dir_path.replace(
|
||||
"-db-", "-analysis-")
|
||||
self.codeql_sarif_path = os.path.join(
|
||||
codeql_sarif_dir_path,
|
||||
(os.path.basename(
|
||||
self.codeql_db_path) +
|
||||
".sarif"))
|
||||
|
||||
edk2_logging.log_progress(f"Analyzing {self.package} ({self.target}) "
|
||||
f"CodeQL database at:\n"
|
||||
f" {self.codeql_db_path}")
|
||||
edk2_logging.log_progress(f"Results will be written to:\n"
|
||||
f" {self.codeql_sarif_path}")
|
||||
|
||||
# Packages are allowed to specify package-specific query specifiers
|
||||
# in the package CI YAML file that override the global query specifier.
|
||||
audit_only = False
|
||||
query_specifiers = None
|
||||
package_config_file = Path(os.path.join(
|
||||
self.package_path, self.package + ".ci.yaml"))
|
||||
plugin_data = None
|
||||
if package_config_file.is_file():
|
||||
with open(package_config_file, 'r') as cf:
|
||||
package_config_file_data = yaml.safe_load(cf)
|
||||
if "CodeQlAnalyze" in package_config_file_data:
|
||||
plugin_data = package_config_file_data["CodeQlAnalyze"]
|
||||
if "AuditOnly" in plugin_data:
|
||||
audit_only = plugin_data["AuditOnly"]
|
||||
if "QuerySpecifiers" in plugin_data:
|
||||
logging.debug(f"Loading CodeQL query specifiers in "
|
||||
f"{str(package_config_file)}")
|
||||
query_specifiers = plugin_data["QuerySpecifiers"]
|
||||
|
||||
global_audit_only = builder.env.GetValue("STUART_CODEQL_AUDIT_ONLY")
|
||||
if global_audit_only:
|
||||
if global_audit_only.strip().lower() == "true":
|
||||
audit_only = True
|
||||
|
||||
if audit_only:
|
||||
logging.info(f"CodeQL Analyze plugin is in audit only mode for "
|
||||
f"{self.package} ({self.target}).")
|
||||
|
||||
# Builds can override the query specifiers defined in this plugin
|
||||
# by setting the value in the STUART_CODEQL_QUERY_SPECIFIERS
|
||||
# environment variable.
|
||||
if not query_specifiers:
|
||||
query_specifiers = builder.env.GetValue(
|
||||
"STUART_CODEQL_QUERY_SPECIFIERS")
|
||||
|
||||
# Use this plugins query set file as the default fallback if it is
|
||||
# not overridden. It is possible the file is not present if modified
|
||||
# locally. In that case, skip the plugin.
|
||||
plugin_query_set = Path(Path(__file__).parent, "CodeQlQueries.qls")
|
||||
|
||||
if not query_specifiers and plugin_query_set.is_file():
|
||||
query_specifiers = str(plugin_query_set.resolve())
|
||||
|
||||
if not query_specifiers:
|
||||
logging.warning("Skipping CodeQL analysis since no CodeQL query "
|
||||
"specifiers were provided.")
|
||||
return 0
|
||||
|
||||
codeql_params = (f'database analyze {self.codeql_db_path} '
|
||||
f'{query_specifiers} --format=sarifv2.1.0 '
|
||||
f'--output={self.codeql_sarif_path} --download '
|
||||
f'--threads=0')
|
||||
|
||||
# CodeQL requires the sarif file parent directory to exist already.
|
||||
Path(self.codeql_sarif_path).parent.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
cmd_ret = RunCmd(self.codeql_path, codeql_params)
|
||||
if cmd_ret != 0:
|
||||
logging.critical(f"CodeQL CLI analysis failed with return code "
|
||||
f"{cmd_ret}.")
|
||||
|
||||
if not os.path.isfile(self.codeql_sarif_path):
|
||||
logging.critical(f"The sarif file {self.codeql_sarif_path} was "
|
||||
f"not created. Analysis cannot continue.")
|
||||
return -1
|
||||
|
||||
filter_pattern_data = []
|
||||
global_filter_file_value = builder.env.GetValue(
|
||||
"STUART_CODEQL_FILTER_FILES")
|
||||
if global_filter_file_value:
|
||||
global_filter_files = global_filter_file_value.strip().split(',')
|
||||
global_filter_files = [Path(f) for f in global_filter_files]
|
||||
|
||||
for global_filter_file in global_filter_files:
|
||||
if global_filter_file.is_file():
|
||||
with open(global_filter_file, 'r') as ff:
|
||||
global_filter_file_data = yaml.safe_load(ff)
|
||||
if "Filters" in global_filter_file_data:
|
||||
current_pattern_data = \
|
||||
global_filter_file_data["Filters"]
|
||||
if type(current_pattern_data) is not list:
|
||||
logging.critical(
|
||||
f"CodeQL pattern data must be a list of "
|
||||
f"strings. Data in "
|
||||
f"{str(global_filter_file.resolve())} is "
|
||||
f"invalid. CodeQL analysis is incomplete.")
|
||||
return -1
|
||||
filter_pattern_data += current_pattern_data
|
||||
else:
|
||||
logging.critical(
|
||||
f"CodeQL global filter file "
|
||||
f"{str(global_filter_file.resolve())} is "
|
||||
f"malformed. Missing Filters section. CodeQL "
|
||||
f"analysis is incomplete.")
|
||||
return -1
|
||||
else:
|
||||
logging.critical(
|
||||
f"CodeQL global filter file "
|
||||
f"{str(global_filter_file.resolve())} was not found. "
|
||||
f"CodeQL analysis is incomplete.")
|
||||
return -1
|
||||
|
||||
if plugin_data and "Filters" in plugin_data:
|
||||
if type(plugin_data["Filters"]) is not list:
|
||||
logging.critical(
|
||||
"CodeQL pattern data must be a list of strings. "
|
||||
"CodeQL analysis is incomplete.")
|
||||
return -1
|
||||
filter_pattern_data.extend(plugin_data["Filters"])
|
||||
|
||||
if filter_pattern_data:
|
||||
logging.info("Applying CodeQL SARIF result filters.")
|
||||
analyze_filter.filter_sarif(
|
||||
self.codeql_sarif_path,
|
||||
self.codeql_sarif_path,
|
||||
filter_pattern_data,
|
||||
split_lines=False)
|
||||
|
||||
with open(self.codeql_sarif_path, 'r') as sf:
|
||||
sarif_file_data = json.load(sf)
|
||||
|
||||
try:
|
||||
# Perform minimal JSON parsing to find the number of errors.
|
||||
total_errors = 0
|
||||
for run in sarif_file_data['runs']:
|
||||
total_errors += len(run['results'])
|
||||
except KeyError:
|
||||
logging.critical("Sarif file does not contain expected data. "
|
||||
"Analysis cannot continue.")
|
||||
return -1
|
||||
|
||||
if total_errors > 0:
|
||||
if audit_only:
|
||||
# Show a warning message so CodeQL analysis is not forgotten.
|
||||
# If the repo owners truly do not want to fix CodeQL issues,
|
||||
# analysis should be disabled entirely.
|
||||
logging.warning(f"{self.package} ({self.target}) CodeQL "
|
||||
f"analysis ignored {total_errors} errors due "
|
||||
f"to audit mode being enabled.")
|
||||
return 0
|
||||
else:
|
||||
logging.error(f"{self.package} ({self.target}) CodeQL "
|
||||
f"analysis failed with {total_errors} errors.")
|
||||
|
||||
return total_errors
|
13
BaseTools/Plugin/CodeQL/CodeQlAnalyze_plug_in.yaml
Normal file
13
BaseTools/Plugin/CodeQL/CodeQlAnalyze_plug_in.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
## @file CodeQlAnalyze_plug_in.py
|
||||
#
|
||||
# Build plugin used to analyze CodeQL results.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
{
|
||||
"scope": "codeql-analyze",
|
||||
"name": "CodeQL Analyze Plugin",
|
||||
"module": "CodeQlAnalyzePlugin"
|
||||
}
|
169
BaseTools/Plugin/CodeQL/CodeQlBuildPlugin.py
Normal file
169
BaseTools/Plugin/CodeQL/CodeQlBuildPlugin.py
Normal file
@ -0,0 +1,169 @@
|
||||
# @file CodeQlBuildPlugin.py
|
||||
#
|
||||
# A build plugin that produces CodeQL results for the present build.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
import glob
|
||||
import logging
|
||||
import os
|
||||
import stat
|
||||
from common import codeql_plugin
|
||||
from pathlib import Path
|
||||
|
||||
from edk2toolext import edk2_logging
|
||||
from edk2toolext.environment.plugintypes.uefi_build_plugin import \
|
||||
IUefiBuildPlugin
|
||||
from edk2toolext.environment.uefi_build import UefiBuilder
|
||||
from edk2toollib.uefi.edk2.path_utilities import Edk2Path
|
||||
from edk2toollib.utility_functions import GetHostInfo, RemoveTree
|
||||
|
||||
|
||||
class CodeQlBuildPlugin(IUefiBuildPlugin):
|
||||
|
||||
def do_pre_build(self, builder: UefiBuilder) -> int:
|
||||
"""CodeQL pre-build functionality.
|
||||
|
||||
Args:
|
||||
builder (UefiBuilder): A UEFI builder object for this build.
|
||||
|
||||
Returns:
|
||||
int: The plugin return code. Zero indicates the plugin ran
|
||||
successfully. A non-zero value indicates an unexpected error
|
||||
occurred during plugin execution.
|
||||
"""
|
||||
|
||||
if not builder.SkipBuild:
|
||||
self.builder = builder
|
||||
self.package = builder.edk2path.GetContainingPackage(
|
||||
builder.edk2path.GetAbsolutePathOnThisSystemFromEdk2RelativePath(
|
||||
builder.env.GetValue("ACTIVE_PLATFORM")
|
||||
)
|
||||
)
|
||||
|
||||
self.target = builder.env.GetValue("TARGET")
|
||||
|
||||
self.build_output_dir = builder.env.GetValue("BUILD_OUTPUT_BASE")
|
||||
|
||||
self.codeql_db_path = codeql_plugin.get_codeql_db_path(
|
||||
builder.ws, self.package, self.target)
|
||||
|
||||
edk2_logging.log_progress(f"{self.package} will be built for CodeQL")
|
||||
edk2_logging.log_progress(f" CodeQL database will be written to "
|
||||
f"{self.codeql_db_path}")
|
||||
|
||||
self.codeql_path = codeql_plugin.get_codeql_cli_path()
|
||||
if not self.codeql_path:
|
||||
logging.critical("CodeQL build enabled but CodeQL CLI application "
|
||||
"not found.")
|
||||
return -1
|
||||
|
||||
# CodeQL can only generate a database on clean build
|
||||
#
|
||||
# Note: builder.CleanTree() cannot be used here as some platforms
|
||||
# have build steps that run before this plugin that store
|
||||
# files in the build output directory.
|
||||
#
|
||||
# CodeQL does not care about with those files or many others such
|
||||
# as the FV directory, build logs, etc. so instead focus on
|
||||
# removing only the directories with compilation/linker output
|
||||
# for the architectures being built (that need clean runs for
|
||||
# CodeQL to work).
|
||||
targets = self.builder.env.GetValue("TARGET_ARCH").split(" ")
|
||||
for target in targets:
|
||||
directory_to_delete = Path(self.build_output_dir, target)
|
||||
|
||||
if directory_to_delete.is_dir():
|
||||
logging.debug(f"Removing {str(directory_to_delete)} to have a "
|
||||
f"clean build for CodeQL.")
|
||||
RemoveTree(str(directory_to_delete))
|
||||
|
||||
# CodeQL CLI does not handle spaces passed in CLI commands well
|
||||
# (perhaps at all) as discussed here:
|
||||
# 1. https://github.com/github/codeql-cli-binaries/issues/73
|
||||
# 2. https://github.com/github/codeql/issues/4910
|
||||
#
|
||||
# Since it's unclear how quotes are handled and may change in the
|
||||
# future, this code is going to use the workaround to place the
|
||||
# command in an executable file that is instead passed to CodeQL.
|
||||
self.codeql_cmd_path = Path(self.build_output_dir, "codeql_build_command")
|
||||
|
||||
build_params = self._get_build_params()
|
||||
|
||||
codeql_build_cmd = ""
|
||||
if GetHostInfo().os == "Windows":
|
||||
self.codeql_cmd_path = self.codeql_cmd_path.parent / (
|
||||
self.codeql_cmd_path.name + '.bat')
|
||||
elif GetHostInfo().os == "Linux":
|
||||
self.codeql_cmd_path = self.codeql_cmd_path.parent / (
|
||||
self.codeql_cmd_path.name + '.sh')
|
||||
codeql_build_cmd += f"#!/bin/bash{os.linesep * 2}"
|
||||
codeql_build_cmd += "build " + build_params
|
||||
|
||||
self.codeql_cmd_path.parent.mkdir(exist_ok=True, parents=True)
|
||||
self.codeql_cmd_path.write_text(encoding='utf8', data=codeql_build_cmd)
|
||||
|
||||
if GetHostInfo().os == "Linux":
|
||||
os.chmod(self.codeql_cmd_path,
|
||||
os.stat(self.codeql_cmd_path).st_mode | stat.S_IEXEC)
|
||||
for f in glob.glob(os.path.join(
|
||||
os.path.dirname(self.codeql_path), '**/*'), recursive=True):
|
||||
os.chmod(f, os.stat(f).st_mode | stat.S_IEXEC)
|
||||
|
||||
codeql_params = (f'database create {self.codeql_db_path} '
|
||||
f'--language=cpp '
|
||||
f'--source-root={builder.ws} '
|
||||
f'--command={self.codeql_cmd_path}')
|
||||
|
||||
# Set environment variables so the CodeQL build command is picked up
|
||||
# as the active build command.
|
||||
#
|
||||
# Note: Requires recent changes in edk2-pytool-extensions (0.20.0)
|
||||
# to support reading these variables.
|
||||
builder.env.SetValue(
|
||||
"EDK_BUILD_CMD", self.codeql_path, "Set in CodeQL Build Plugin")
|
||||
builder.env.SetValue(
|
||||
"EDK_BUILD_PARAMS", codeql_params, "Set in CodeQL Build Plugin")
|
||||
|
||||
return 0
|
||||
|
||||
def _get_build_params(self) -> str:
|
||||
"""Returns the build command parameters for this build.
|
||||
|
||||
Based on the well-defined `build` command-line parameters.
|
||||
|
||||
Returns:
|
||||
str: A string representing the parameters for the build command.
|
||||
"""
|
||||
build_params = f"-p {self.builder.env.GetValue('ACTIVE_PLATFORM')}"
|
||||
build_params += f" -b {self.target}"
|
||||
build_params += f" -t {self.builder.env.GetValue('TOOL_CHAIN_TAG')}"
|
||||
|
||||
max_threads = self.builder.env.GetValue('MAX_CONCURRENT_THREAD_NUMBER')
|
||||
if max_threads is not None:
|
||||
build_params += f" -n {max_threads}"
|
||||
|
||||
rt = self.builder.env.GetValue("TARGET_ARCH").split(" ")
|
||||
for t in rt:
|
||||
build_params += " -a " + t
|
||||
|
||||
if (self.builder.env.GetValue("BUILDREPORTING") == "TRUE"):
|
||||
build_params += (" -y " +
|
||||
self.builder.env.GetValue("BUILDREPORT_FILE"))
|
||||
rt = self.builder.env.GetValue("BUILDREPORT_TYPES").split(" ")
|
||||
for t in rt:
|
||||
build_params += " -Y " + t
|
||||
|
||||
# add special processing to handle building a single module
|
||||
mod = self.builder.env.GetValue("BUILDMODULE")
|
||||
if (mod is not None and len(mod.strip()) > 0):
|
||||
build_params += " -m " + mod
|
||||
edk2_logging.log_progress("Single Module Build: " + mod)
|
||||
|
||||
build_vars = self.builder.env.GetAllBuildKeyValues(self.target)
|
||||
for key, value in build_vars.items():
|
||||
build_params += " -D " + key + "=" + value
|
||||
|
||||
return build_params
|
13
BaseTools/Plugin/CodeQL/CodeQlBuild_plug_in.yaml
Normal file
13
BaseTools/Plugin/CodeQL/CodeQlBuild_plug_in.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
## @file CodeQlBuild_plug_in.py
|
||||
#
|
||||
# Build plugin used to produce a CodeQL database from a build.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
{
|
||||
"scope": "codeql-build",
|
||||
"name": "CodeQL Build Plugin",
|
||||
"module": "CodeQlBuildPlugin"
|
||||
}
|
118
BaseTools/Plugin/CodeQL/CodeQlQueries.qls
Normal file
118
BaseTools/Plugin/CodeQL/CodeQlQueries.qls
Normal file
@ -0,0 +1,118 @@
|
||||
---
|
||||
- description: C++ queries
|
||||
|
||||
- queries: '.'
|
||||
from: codeql/cpp-queries
|
||||
|
||||
##########################################################################################
|
||||
# Queries
|
||||
##########################################################################################
|
||||
|
||||
## Errors
|
||||
- include:
|
||||
id: cpp/badoverflowguard
|
||||
- include:
|
||||
id: cpp/infiniteloop
|
||||
- include:
|
||||
id: cpp/likely-bugs/memory-management/v2/conditionally-uninitialized-variable
|
||||
- include:
|
||||
id: cpp/missing-null-test
|
||||
- include:
|
||||
id: cpp/missing-return
|
||||
- include:
|
||||
id: cpp/no-space-for-terminator
|
||||
- include:
|
||||
id: cpp/pointer-overflow-check
|
||||
- include:
|
||||
id: cpp/redundant-null-check-simple
|
||||
- include:
|
||||
id: cpp/sizeof/const-int-argument
|
||||
- include:
|
||||
id: cpp/sizeof/sizeof-or-operation-as-argument
|
||||
- include:
|
||||
id: cpp/unguardednullreturndereferenc
|
||||
- include:
|
||||
id: cpp/very-likely-overrunning-write
|
||||
|
||||
## Warnings
|
||||
- include:
|
||||
id: cpp/comparison-with-wider-type
|
||||
- include:
|
||||
id: cpp/conditionallyuninitializedvariable
|
||||
- include:
|
||||
id: cpp/comparison-precedence
|
||||
- include:
|
||||
id: cpp/implicit-bitfield-downcast
|
||||
- include:
|
||||
id: cpp/infinite-loop-with-unsatisfiable-exit-condition
|
||||
- include:
|
||||
id: cpp/offset-use-before-range-check
|
||||
- include:
|
||||
id: cpp/overflow-buffer
|
||||
- include:
|
||||
id: cpp/overflow-calculated
|
||||
- include:
|
||||
id: cpp/overflow-destination
|
||||
- include:
|
||||
id: cpp/paddingbyteinformationdisclosure
|
||||
- include:
|
||||
id: cpp/return-stack-allocated-memory
|
||||
- include:
|
||||
id: cpp/static-buffer-overflow
|
||||
- include:
|
||||
id: cpp/unsigned-comparison-zero
|
||||
- include:
|
||||
id: cpp/uselesstest
|
||||
|
||||
## Recommendations
|
||||
- include:
|
||||
id: cpp/missing-header-guard
|
||||
- include:
|
||||
id: cpp/unused-local-variable
|
||||
- include:
|
||||
id: cpp/unused-static-function
|
||||
- include:
|
||||
id: cpp/unused-static-variable
|
||||
|
||||
# Note: Some queries above are not active by default with the below filter.
|
||||
# Update the filter and run the queries again to get all results.
|
||||
- include:
|
||||
tags:
|
||||
- "security"
|
||||
- "correctness"
|
||||
severity:
|
||||
- "error"
|
||||
- "warning"
|
||||
- "recommendation"
|
||||
|
||||
# Specifically hide the results of these.
|
||||
#
|
||||
# The following rules have been evaluated and explicitly not included for the following reasons:
|
||||
# - `cpp/allocation-too-small` - Appears to be hardcoded for C standard library functions `malloc`, `calloc`,
|
||||
# `realloc`, so it consumes time without much value with custom allocation functions in the codebase.
|
||||
# - `cpp/commented-out-code` - Triggers often. Needs further review.
|
||||
# - `cpp/duplicate-include-guard` - The <Phase>EntryPoint.h files includes a common include guard value
|
||||
# `__MODULE_ENTRY_POINT_H__`. This was the only occurrence found. So not very useful.
|
||||
# - `cpp/invalid-pointer-deref` - Very limited results with what appear to be false positives.
|
||||
# - `cpp/use-of-goto` - Goto is valid and allowed in the codebase.
|
||||
# - `cpp/useless-expression` - Triggers too often on cases where a NULL lib implementation is provided for a function.
|
||||
# Because the implementation simply returns, the check considers it useless.
|
||||
# - `cpp/weak-crypto/*` - Crypto algorithms are tracked outside CodeQL.
|
||||
- exclude:
|
||||
id: cpp/allocation-too-small
|
||||
- exclude:
|
||||
id: cpp/commented-out-code
|
||||
- exclude:
|
||||
id: cpp/duplicate-include-guard
|
||||
- exclude:
|
||||
id: cpp/invalid-pointer-deref
|
||||
- exclude:
|
||||
id: cpp/use-of-goto
|
||||
- exclude:
|
||||
id: cpp/useless-expression
|
||||
- exclude:
|
||||
id: cpp/weak-crypto/banned-hash-algorithms
|
||||
- exclude:
|
||||
id: cpp/weak-crypto/capi/banned-modes
|
||||
- exclude:
|
||||
id: cpp/weak-crypto/openssl/banned-hash-algorithms
|
388
BaseTools/Plugin/CodeQL/Readme.md
Normal file
388
BaseTools/Plugin/CodeQL/Readme.md
Normal file
@ -0,0 +1,388 @@
|
||||
# CodeQL Plugin
|
||||
|
||||
The set of CodeQL plugins provided include two main plugins that seamlessly integrate into a Stuart build environment:
|
||||
|
||||
1. `CodeQlBuildPlugin` - Used to produce a CodeQL database from a build.
|
||||
2. `CodeQlAnalyzePlugin` - Used to analyze a CodeQL database.
|
||||
|
||||
While CodeQL can be run in a CI environment with other approaches. This plugin offers the following advantages:
|
||||
|
||||
1. Provides exactly the same results locally as on a CI server.
|
||||
2. Integrates very well into VS Code.
|
||||
3. Very simple to use - just use normal Stuart update and build commands.
|
||||
4. Very simple to understand - minimally wraps the official CodeQL CLI.
|
||||
5. Very simple to integrate - works like any other Stuart build plugin.
|
||||
- Integration is usually just a few lines of code.
|
||||
6. Portable - not tied to Azure DevOps specific, GitHub specific, or other host infrastructure.
|
||||
7. Versioned - the query and filters are versioned in source control so easy to find and track.
|
||||
|
||||
It is very important to read the Integration Instructions in this file and determine how to best integrate the
|
||||
CodeQL plugin into your environment.
|
||||
|
||||
Due to the total size of dependencies required to run CodeQL and the flexibility needed by a platform to determine what
|
||||
CodeQL queries to run and how to interpret results, a number of configuration options are provided to allow a high
|
||||
degree of flexibility during platform integration.
|
||||
|
||||
This document is focused on those setting up the CodeQL plugin in their environment. Once setup, end users simply need
|
||||
to use their normal build commands and process and CodeQL will be integrated with it. The most relevant section for
|
||||
such users is [Local Development Tips](#local-development-tips).
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Database and Analysis Result Locations](#database-and-analysis-result-locations)
|
||||
2. [Global Configuration](#global-configuration)
|
||||
3. [Package-Specific Configuration](#package-specific-configuration)
|
||||
4. [Filter Patterns](#filter-patterns)
|
||||
5. [Integration Instructions](#integration-instructions)
|
||||
- [Integration Step 1 - Choose Scopes](#integration-step-1---choose-scopes)
|
||||
- [Scopes Available](#scopes-available)
|
||||
- [Integration Step 2 - Choose CodeQL Queries](#integration-step-2---choose-codeql-queries)
|
||||
- [Integration Step 3 - Determine Global Configuration Values](#integration-step-3---determine-global-configuration-values)
|
||||
- [Integration Step 4 - Determine Package-Specific Configuration Values](#integration-step-4---determine-package-specific-configuration-values)
|
||||
- [Integration Step 5 - Testing](#integration-step-5---testing)
|
||||
- [Integration Step 6 - Define Inclusion and Exclusion Filter Patterns](#integration-step-6---define-inclusion-and-exclusion-filter-patterns)
|
||||
6. [High-Level Operation](#high-level-operation)
|
||||
- [CodeQlBuildPlugin](#codeqlbuildplugin)
|
||||
- [CodeQlAnalyzePlugin](#codeqlanalyzeplugin)
|
||||
7. [Local Development Tips](#local-development-tips)
|
||||
8. [Resolution Guidelines](#resolution-guidelines)
|
||||
|
||||
## Database and Analysis Result Locations
|
||||
|
||||
The CodeQL database is written to a directory unique to the package and target being built:
|
||||
|
||||
`Build/codeql-db-<package>-<target>-<instance>`
|
||||
|
||||
For example: `Build/codeql-db-mdemodulepkg-debug-0`
|
||||
|
||||
The plugin does not delete or overwrite existing databases, the instance value is simply increased. This is
|
||||
because databases are large, take a long time to generate, and are important for reproducing analysis results. The user
|
||||
is responsible for deleting database directories when they are no longer needed.
|
||||
|
||||
Similarly, analysis results are written to a directory unique to the package and target. For analysis, results are
|
||||
stored in individual files so those files are stored in a single directory.
|
||||
|
||||
For example, all analysis results for the above package and target will be stored in:
|
||||
`codeql-analysis-mdemodulepkg-debug`
|
||||
|
||||
CodeQL results are stored in [SARIF](https://sarifweb.azurewebsites.net/) (Static Analysis Results Interchange Format)
|
||||
([CodeQL SARIF documentation](https://codeql.github.com/docs/codeql-cli/sarif-output/)) files. Each SARIF file
|
||||
corresponding to a database will be stored in a file with an instance matching the database instance.
|
||||
|
||||
For example, the analysis result file for the above database would be stored in this file:
|
||||
`codeql-analysis-mdemodulepkg-debug/codeql-db-mdemodulepkg-debug-0.sarif`
|
||||
|
||||
Result files are overwritten. This is because result files are quick to generate and need to represent the latest
|
||||
results for the last analysis operation performed. The user is responsible for backing up SARIF result files if they
|
||||
need to saved.
|
||||
|
||||
## Global Configuration
|
||||
|
||||
Global configuration values are specified with build environment variables.
|
||||
|
||||
These values are all optional. They provide a convenient mechanism for a build script to set the value for all packages
|
||||
built by the script.
|
||||
|
||||
- `STUART_CODEQL_AUDIT_ONLY` - If `true` (case insensitive), `CodeQlAnalyzePlugin` will be in audit-only mode. In this
|
||||
mode all CodeQL failures are ignored.
|
||||
- `STUART_CODEQL_PATH` - The path to the CodeQL CLI application to use.
|
||||
- `STUART_CODEQL_QUERY_SPECIFIERS` - The CodeQL CLI query specifiers to use. See [Running codeql database analyze](https://codeql.github.com/docs/codeql-cli/analyzing-databases-with-the-codeql-cli/#running-codeql-database-analyze)
|
||||
for possible options.
|
||||
- `STUART_CODEQL_FILTER_FILES` - The path to "filter" files that contains filter patterns as described in
|
||||
[Filter Patterns](#filter-patterns).
|
||||
- More than one file may be specified by separating each absolute file path with a comma.
|
||||
- This might be useful to reference a global filter file from an upstream repo and also include a global filter
|
||||
file for the local repo.
|
||||
- Filters are concatenated in the order of files in the variable. Patterns in later files can override patterns
|
||||
in earlier files.
|
||||
- The file only needs to contain a list of filter pattern strings under a `"Filters"` key. For example:
|
||||
|
||||
```yaml
|
||||
{
|
||||
"Filters": [
|
||||
"<pattern-line-1>",
|
||||
"<pattern-line-2>"
|
||||
]
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
Comments are allowed in the filter files and begin with `#` (like a normal YAML file).
|
||||
|
||||
## Package-Specific Configuration
|
||||
|
||||
Package-specific configuration values reuse existing package-level configuration approaches to simplify adjusting
|
||||
CodeQL plugin behavior per package.
|
||||
|
||||
These values are all optional. They provide a convenient mechanism for a package owner to adjust settings specific to
|
||||
the package.
|
||||
|
||||
``` yaml
|
||||
"CodeQlAnalyze": {
|
||||
"AuditOnly": False, # Don't fail the build if there are errors. Just log them.
|
||||
"QuerySpecifiers": "" # Query specifiers to pass to CodeQL CLI.
|
||||
"Filters": "" # Inclusion/exclusion filters
|
||||
}
|
||||
```
|
||||
|
||||
> _NOTE:_ If a global filter set is provided via `STUART_CODEQL_FILTER_FILES` and a package has a package-specific
|
||||
> list, then the package-specific filter list (in a package CI YAML file) is appended onto the global filter list and
|
||||
> may be used to override settings in the global list.
|
||||
|
||||
The format used to specify items in `"Filters"` is specified in [Filter Patterns](#filter-patterns).
|
||||
|
||||
## Filter Patterns
|
||||
|
||||
As you inspect results, you may want to include or exclude certain sets of results. For example, exclude some files by
|
||||
file path entirely or adjust the CodeQL rule applied to a certain file. This plugin reuses logic from a popular
|
||||
GitHub Action called [`filter-sarif`](https://github.com/advanced-security/filter-sarif) to allow filtering as part of
|
||||
the plugin analysis process.
|
||||
|
||||
If any results are excluded using filters, the results are removed from the SARIF file. This allows the exclude results
|
||||
seen locally to exactly match the results on the CI server.
|
||||
|
||||
Read the ["Patterns"](https://github.com/advanced-security/filter-sarif#patterns) section there for more details. The
|
||||
patterns section is also copied below with some updates to make the information more relevant for an edk2 codebase
|
||||
for convenience.
|
||||
|
||||
Each pattern line is of the form:
|
||||
|
||||
```plaintext
|
||||
[+/-]<file pattern>[:<rule pattern>]
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```yaml
|
||||
-**/*Test*.c:** # exclusion pattern: remove all alerts from all test files
|
||||
-**/*Test*.c # ditto, short form of the line above
|
||||
+**/*.c:cpp/infiniteloop # inclusion pattern: This line has precedence over the first two
|
||||
# and thus "allow lists" alerts of type "cpp/infiniteloop"
|
||||
**/*.c:cpp/infiniteloop # ditto, the "+" in inclusion patterns is optional
|
||||
** # allow all alerts in all files (reverses all previous lines)
|
||||
```
|
||||
|
||||
- The path separator character in patterns is always `/`, independent of the platform the code is running on and
|
||||
independent of the paths in the SARIF file.
|
||||
- `*` matches any character, except a path separator
|
||||
- `**` matches any character and is only allowed between path separators, e.g. `/**/file.txt`, `**/file.txt` or `**`.
|
||||
NOT allowed: `**.txt`, `/etc**`
|
||||
- The rule pattern is optional. If omitted, it will apply to alerts of all types.
|
||||
- Subsequent lines override earlier ones. By default all alerts are included.
|
||||
- If you need to use the literals `+`, `-`, `\` or `:` in your pattern, you can escape them with `\`, e.g.
|
||||
`\-this/is/an/inclusion/file/pattern\:with-a-semicolon:and/a/rule/pattern/with/a/\\/backslash`. For `+` and `-`, this
|
||||
is only necessary if they appear at the beginning of the pattern line.
|
||||
|
||||
## Integration Instructions
|
||||
|
||||
First, note that most CodeQL CLI operations will take a long time the first time they are run. This is due to:
|
||||
|
||||
1. Downloads - Downloading the CodeQL CLI binary (during `stuart_update`) and downloading CodeQL queries during
|
||||
CodeQL plugin execution
|
||||
2. Cache not established - CodeQL CLI caches data as it performs analysis. The first time analysis is performed will
|
||||
take more time than in the future.
|
||||
|
||||
Second, these are build plugins. This means a build needs to take place for the plugins to run. This typically happens
|
||||
in the following two scenarios:
|
||||
|
||||
1. `stuart_build` - A single package is built and the build process is started by the stuart tools.
|
||||
2. `stuart_ci_build` - A number of packages may be built and the build process is started by the `CompilerPlugin`.
|
||||
|
||||
In any case, each time a package is built, the CodeQL plugins will be run if their scopes are active.
|
||||
|
||||
### Integration Step 1 - Choose Scopes
|
||||
|
||||
Decide which scopes need to be enabled in your platform, see [Scopes Available](#scopes-available).
|
||||
|
||||
Consider using a build profile to enable CodeQL so developers and pipelines can use the profile when they are
|
||||
interested in CodeQL results but in other cases they can easily work without CodeQL in the way.
|
||||
|
||||
Furthermore, build-script specific command-line parameters might be useful to control CodeQL scopes and other
|
||||
behavior.
|
||||
|
||||
#### Scopes Available
|
||||
|
||||
This CodeQL plugin leverages scopes to control major pieces of functionality. Any combination of scopes can be
|
||||
returned from the `GetActiveScopes()` function in the platform settings manager to add and remove functionality.
|
||||
|
||||
Plugin scopes:
|
||||
|
||||
- `codeql-analyze` - Activate `CodeQlAnalyzePlugin` to perform post-build analysis of the last generated database for
|
||||
the package and target specified.
|
||||
- `codeql-build` - Activate `CodeQlBuildPlugin` to hook the firmware build in pre-build such that the build will
|
||||
generate a CodeQL database during build.
|
||||
|
||||
In most cases, to perform a full CodeQL run, `codeql-build` should be enabled so a new CodeQL database is generated
|
||||
during build and `codeql-analyze` should be be enabled so analysis of that database is performed after the build is
|
||||
completed.
|
||||
|
||||
External dependency scopes:
|
||||
|
||||
- `codeql-ext-dep` - Downloads the cross-platform CodeQL CLI as an external dependency.
|
||||
- `codeql-linux-ext-dep` - Downloads the Linux CodeQL CLI as an external dependency.
|
||||
- `codeql-windows-ext-dep` - Downloads the Windows CodeQL CLI as an external dependency.
|
||||
|
||||
Note, that the CodeQL CLI is large in size. Sizes as of the [v2.11.2 release](https://github.com/github/codeql-cli-binaries/releases/tag/v2.11.2).
|
||||
|
||||
| Cross-platform | Linux | Windows |
|
||||
|:--------------:|:------:|:-------:|
|
||||
| 934 MB | 415 MB | 290 MB |
|
||||
|
||||
Therefore, the following is recommended:
|
||||
|
||||
1. **Ideal** - Create container images for build agents and install the CodeQL CLI for the container OS into the
|
||||
container.
|
||||
2. Leverage host-OS detection (e.g. [`GetHostInfo()`](https://github.com/tianocore/edk2-pytool-library/blob/42ad6561af73ba34564f1577f64f7dbaf1d0a5a2/edk2toollib/utility_functions.py#L112))
|
||||
to set the scope for the appropriate operating system. This will download the much smaller OS-specific application.
|
||||
|
||||
> _NOTE:_ You should never have more than one CodeQL external dependency scope enabled at a time.
|
||||
|
||||
### Integration Step 2 - Choose CodeQL Queries
|
||||
|
||||
Determine which queries need to be run against packages in your repo. In most cases, the same set of queries will be
|
||||
run against all packages. It is also possible to customize the queries run at the package level.
|
||||
|
||||
The default set of Project Mu CodeQL queries is specified in the `MuCodeQlQueries.qls` file in this plugin.
|
||||
|
||||
> _NOTE:_ The queries in `MuCodeQlQueries.qls` may change at any time. If you do not want these changes to impact
|
||||
> your platform, do not relay on option (3).
|
||||
|
||||
The plugin decides what queries to run based on the following, in order of preference:
|
||||
|
||||
1. Package CI YAML file query specifier
|
||||
2. Build environment variable query specifier
|
||||
3. Plugin default query set file
|
||||
|
||||
For details on how to set (1) and (2), see the Package CI Configuration and Environment Variable sections respectively.
|
||||
|
||||
> _NOTE:_ The value specified is directly passed as a `query specifier` to CodeQL CLI. Therefore, the arguments
|
||||
> allowed by the `<query-specifiers>` argument of CodeQL CLI are allowed here. See
|
||||
> [Running codeql database analyze](https://codeql.github.com/docs/codeql-cli/analyzing-databases-with-the-codeql-cli/#running-codeql-database-analyze).
|
||||
|
||||
A likely scenario is that a platform needs to run local/closed source queries in addition to the open-source queries.
|
||||
There's various ways to handle that:
|
||||
|
||||
1. Create a query specifier that includes all the queries needed, both public and private and use that query specifier,
|
||||
either globally or at package-level.
|
||||
|
||||
For example, at the global level - `STUART_CODEQL_QUERY_SPECIFIERS` = _"Absolute_path_to_AllMyQueries.qls"_
|
||||
|
||||
2. Specify a query specifier that includes the closed sources queries and reuse the public query list provided by
|
||||
this plugin.
|
||||
|
||||
For example, at the global level - `STUART_CODEQL_QUERY_SPECIFIERS` = _"Absolute_path_to_MuCodeQlQueries.qls
|
||||
Absolute_path_to_ClosedSourceQueries.qls"_
|
||||
|
||||
Refer to the CodeQL documentation noted above on query specifiers to devise other options.
|
||||
|
||||
### Integration Step 3 - Determine Global Configuration Values
|
||||
|
||||
Review the Environment Variable section to determine which, if any, global values need to be set in your build script.
|
||||
|
||||
### Integration Step 4 - Determine Package-Specific Configuration Values
|
||||
|
||||
Review the Package CI Configuration section to determine which, if any, global values need to be set in your
|
||||
package's CI YAML file.
|
||||
|
||||
### Integration Step 5 - Testing
|
||||
|
||||
Verify a `stuart_update` and `stuart_build` (or `stuart_ci_build`) command work.
|
||||
|
||||
### Integration Step 6 - Define Inclusion and Exclusion Filter Patterns
|
||||
|
||||
After reviewing the test results from Step 5, determine if you need to apply any filters as described in
|
||||
[Filter Patterns](#filter-patterns).
|
||||
|
||||
## High-Level Operation
|
||||
|
||||
This section summarizes the complete CodeQL plugin flow. This is to help developers understand basic theory of
|
||||
operation behind the plugin and can be skipped by anyone not interested in those details.
|
||||
|
||||
### CodeQlBuildPlugin
|
||||
|
||||
1. Register a pre-build hook
|
||||
2. Determine the package and target being built
|
||||
3. Determine the best CodeQL CLI path to use
|
||||
- First choice, the `STUART_CODEQL_PATH` environment variable
|
||||
- Note: This is set by the CodeQL CLI external dependency if that is used
|
||||
- Second choice, `codeql` as found on the system path
|
||||
4. Determine the directory name for the CodeQL database
|
||||
- Format: `Build/codeql-db-<package>-<target>-<instance>`
|
||||
5. Clean the build directory of the active platform and target
|
||||
- CodeQL database generation only works on clean builds
|
||||
6. Ensure the "build" step is not skipped as a build is needed to generate a CodeQL database
|
||||
7. Build a CodeQL file that wraps around the edk2 build
|
||||
- Written to the package build directory
|
||||
- Example: `Build/MdeModulePkg/VS2022/codeql_build_command.bat`
|
||||
8. Set the variables necessary for stuart to call CodeQL CLI during the build phase
|
||||
- Sets `EDK_BUILD_CMD` and `EDK_BUILD_PARAMS`
|
||||
|
||||
### CodeQlAnalyzePlugin
|
||||
|
||||
1. Register a post-build hook
|
||||
2. Determine the package and target being built
|
||||
3. Determine the best CodeQL CLI path to use
|
||||
- First choice, the `STUART_CODEQL_PATH` environment variable
|
||||
- Note: This is set by the CodeQL CLI external dependency if that is used
|
||||
- Second choice, `codeql` as found on the system path
|
||||
4. Determine the directory name for the most recent CodeQL database
|
||||
- Format: `Build/codeql-db-<package>-<target>-<instance>`
|
||||
5. Determine plugin audit status for the given package and target
|
||||
- Check if `AuditOnly` is enabled either globally or for the package
|
||||
6. Determine the CodeQL query specifiers to use for the given package and target
|
||||
- First choice, the package CI YAML file value
|
||||
- Second choice, the `STUART_CODEQL_QUERY_SPECIFIERS`
|
||||
- Third choice, use `CodeQlQueries.qls` (in the plugin directory)
|
||||
7. Run CodeQL CLI to perform database analysis
|
||||
8. Parse the analysis SARIF file to determine the number of CodeQL failures
|
||||
9. Return the number of failures (or zero if `AuditOnly` is enabled)
|
||||
|
||||
## Local Development Tips
|
||||
|
||||
This section contains helpful tips to expedite common scenarios when working with CodeQL locally.
|
||||
|
||||
1. Pre-build, Build, and Post-Build
|
||||
|
||||
Generating a database requires the pre-build and build steps. Analyzing a database requires the post-build step.
|
||||
|
||||
Therefore, if you are making tweaks that don't affect the build, such as modifying the CodeQL queries used or level
|
||||
of severity reported, you can save time by skipping pre-build and post-build (e.g. `--skipprebuild` and
|
||||
`--skipbuild`).
|
||||
|
||||
2. Scopes
|
||||
|
||||
Similar to (1), add/remove `codeql-build` and `codeql-analyze` from the active scopes to save time depending on what
|
||||
you are trying to do.
|
||||
|
||||
If you are focusing on coding, remove the code CodeQL scopes if they are active. If you are ready to check your
|
||||
changes against CodeQL, simply add the scopes back. It is recommended to use build profiles to do this more
|
||||
conveniently.
|
||||
|
||||
If you already have CodeQL CLI enabled, you can remove the `codeql-ext-dep` scope locally. The build will use the
|
||||
`codeql` command on your path.
|
||||
|
||||
3. CodeQL Output is in the CI Build Log
|
||||
|
||||
To see exactly which queries CodeQL ran or why it might be taking longer than expected, look in the CI build log
|
||||
(i.e. `Build/CI_BUILDLOG.txt`) where the CodeQL CLI application output is written.
|
||||
|
||||
Search for the text you see in the progress output (e.g. "Analyzing _MdeModulePkg_ (_DEBUG_) CodeQL database at")
|
||||
to jump to the section of the log just before the CodeQL CLI is invoked.
|
||||
|
||||
4. Use a SARIF Viewer to Read Results
|
||||
|
||||
The [SARIF Viewer extension for VS Code](https://marketplace.visualstudio.com/items?itemName=MS-SarifVSCode.sarif-viewer)
|
||||
can open the .sarif file generated by this plugin and allow you to click links directly to the problem area in source
|
||||
files.
|
||||
|
||||
## Resolution Guidelines
|
||||
|
||||
This section captures brief guidelines to keep in mind while resolving CodeQL issues.
|
||||
|
||||
1. Look at surrounding code. Changes should always take into account the context of nearby code. The new logic may
|
||||
need to account conditions not immediately obvious based on the issue alone. It is easy to focus only on the line
|
||||
of code highlighted by CodeQL and miss the code's role in the big picture.
|
||||
2. A CodeQL alert may be benign but the code can be refactored to prevent the alert. Often refactoring the code makes
|
||||
the code intention clearer and avoids an unnecessary exception.
|
||||
3. Consider adding unit tests while making CodeQL fixes especially for commonly used code and code with a high volume
|
||||
of CodeQL alerts.
|
0
BaseTools/Plugin/CodeQL/analyze/__init__.py
Normal file
0
BaseTools/Plugin/CodeQL/analyze/__init__.py
Normal file
184
BaseTools/Plugin/CodeQL/analyze/analyze_filter.py
Normal file
184
BaseTools/Plugin/CodeQL/analyze/analyze_filter.py
Normal file
@ -0,0 +1,184 @@
|
||||
# @file analyze_filter.py
|
||||
#
|
||||
# Filters results in a SARIF file.
|
||||
#
|
||||
# Apache License
|
||||
# Version 2.0, January 2004
|
||||
# http://www.apache.org/licenses/
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# This file has been altered from its original form. Based on code in:
|
||||
# https://github.com/advanced-security/filter-sarif
|
||||
#
|
||||
# It primarily contains modifications made to integrate with the CodeQL plugin.
|
||||
#
|
||||
# Specifically:
|
||||
# https://github.com/advanced-security/filter-sarif/blob/main/filter_sarif.py
|
||||
#
|
||||
# View the full and complete license as provided by that repository here:
|
||||
# https://github.com/advanced-security/filter-sarif/blob/main/LICENSE
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
##
|
||||
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
from os import PathLike
|
||||
from typing import Iterable, List, Tuple
|
||||
|
||||
from analyze.globber import match
|
||||
|
||||
|
||||
def _match_path_and_rule(
|
||||
path: str, rule: str, patterns: Iterable[str]) -> bool:
|
||||
"""Returns whether a given path matches a given rule.
|
||||
|
||||
Args:
|
||||
path (str): A file path string.
|
||||
rule (str): A rule file path string.
|
||||
patterns (Iterable[str]): An iterable of pattern strings.
|
||||
|
||||
Returns:
|
||||
bool: True if the path matches a rule. Otherwise, False.
|
||||
"""
|
||||
result = True
|
||||
for s, fp, rp in patterns:
|
||||
if match(rp, rule) and match(fp, path):
|
||||
result = s
|
||||
return result
|
||||
|
||||
|
||||
def _parse_pattern(line: str) -> Tuple[str]:
|
||||
"""Parses a given pattern line.
|
||||
|
||||
Args:
|
||||
line (str): The line string that contains the rule.
|
||||
|
||||
Returns:
|
||||
Tuple[str]: The parsed sign, file pattern, and rule pattern from the
|
||||
line.
|
||||
"""
|
||||
sep_char = ':'
|
||||
esc_char = '\\'
|
||||
file_pattern = ''
|
||||
rule_pattern = ''
|
||||
seen_separator = False
|
||||
sign = True
|
||||
|
||||
# inclusion or exclusion pattern?
|
||||
u_line = line
|
||||
if line:
|
||||
if line[0] == '-':
|
||||
sign = False
|
||||
u_line = line[1:]
|
||||
elif line[0] == '+':
|
||||
u_line = line[1:]
|
||||
|
||||
i = 0
|
||||
while i < len(u_line):
|
||||
c = u_line[i]
|
||||
i = i + 1
|
||||
if c == sep_char:
|
||||
if seen_separator:
|
||||
raise Exception(
|
||||
'Invalid pattern: "' + line + '" Contains more than one '
|
||||
'separator!')
|
||||
seen_separator = True
|
||||
continue
|
||||
elif c == esc_char:
|
||||
next_c = u_line[i] if (i < len(u_line)) else None
|
||||
if next_c in ['+' , '-', esc_char, sep_char]:
|
||||
i = i + 1
|
||||
c = next_c
|
||||
if seen_separator:
|
||||
rule_pattern = rule_pattern + c
|
||||
else:
|
||||
file_pattern = file_pattern + c
|
||||
|
||||
if not rule_pattern:
|
||||
rule_pattern = '**'
|
||||
|
||||
return sign, file_pattern, rule_pattern
|
||||
|
||||
|
||||
def filter_sarif(input_sarif: PathLike,
|
||||
output_sarif: PathLike,
|
||||
patterns: List[str],
|
||||
split_lines: bool) -> None:
|
||||
"""Filters a SARIF file with a given set of filter patterns.
|
||||
|
||||
Args:
|
||||
input_sarif (PathLike): Input SARIF file path.
|
||||
output_sarif (PathLike): Output SARIF file path.
|
||||
patterns (PathLike): List of filter pattern strings.
|
||||
split_lines (PathLike): Whether to split lines in individual patterns.
|
||||
"""
|
||||
if split_lines:
|
||||
tmp = []
|
||||
for p in patterns:
|
||||
tmp = tmp + re.split('\r?\n', p)
|
||||
patterns = tmp
|
||||
|
||||
patterns = [_parse_pattern(p) for p in patterns if p]
|
||||
|
||||
logging.debug('Given patterns:')
|
||||
for s, fp, rp in patterns:
|
||||
logging.debug(
|
||||
'files: {file_pattern} rules: {rule_pattern} ({sign})'.format(
|
||||
file_pattern=fp,
|
||||
rule_pattern=rp,
|
||||
sign='positive' if s else 'negative'))
|
||||
|
||||
with open(input_sarif, 'r') as f:
|
||||
s = json.load(f)
|
||||
|
||||
for run in s.get('runs', []):
|
||||
if run.get('results', []):
|
||||
new_results = []
|
||||
for r in run['results']:
|
||||
if r.get('locations', []):
|
||||
new_locations = []
|
||||
for l in r['locations']:
|
||||
# TODO: The uri field is optional. We might have to
|
||||
# fetch the actual uri from "artifacts" via
|
||||
# "index"
|
||||
# (see https://github.com/microsoft/sarif-tutorials/blob/main/docs/2-Basics.md#-linking-results-to-artifacts)
|
||||
uri = l.get(
|
||||
'physicalLocation', {}).get(
|
||||
'artifactLocation', {}).get(
|
||||
'uri', None)
|
||||
|
||||
# TODO: The ruleId field is optional and potentially
|
||||
# ambiguous. We might have to fetch the actual
|
||||
# ruleId from the rule metadata via the ruleIndex
|
||||
# field.
|
||||
# (see https://github.com/microsoft/sarif-tutorials/blob/main/docs/2-Basics.md#rule-metadata)
|
||||
ruleId = r['ruleId']
|
||||
|
||||
if (uri is None or
|
||||
_match_path_and_rule(uri, ruleId, patterns)):
|
||||
new_locations.append(l)
|
||||
r['locations'] = new_locations
|
||||
if new_locations:
|
||||
new_results.append(r)
|
||||
else:
|
||||
# locations array doesn't exist or is empty, so we can't
|
||||
# match on anything. Therefore, we include the result in
|
||||
# the output.
|
||||
new_results.append(r)
|
||||
run['results'] = new_results
|
||||
|
||||
with open(output_sarif, 'w') as f:
|
||||
json.dump(s, f, indent=2)
|
127
BaseTools/Plugin/CodeQL/analyze/globber.py
Normal file
127
BaseTools/Plugin/CodeQL/analyze/globber.py
Normal file
@ -0,0 +1,127 @@
|
||||
# @file globber.py
|
||||
#
|
||||
# Provides global functionality for use by the CodeQL plugin.
|
||||
#
|
||||
# Copyright 2019 Jaakko Kangasharju
|
||||
#
|
||||
# Apache License
|
||||
# Version 2.0, January 2004
|
||||
# http://www.apache.org/licenses/
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# This file has been altered from its original form. Based on code in:
|
||||
# https://github.com/advanced-security/filter-sarif
|
||||
#
|
||||
# Specifically:
|
||||
# https://github.com/advanced-security/filter-sarif/blob/main/filter_sarif.py
|
||||
#
|
||||
# It primarily contains modifications made to integrate with the CodeQL plugin.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
##
|
||||
|
||||
import re
|
||||
|
||||
_double_star_after_invalid_regex = re.compile(r'[^/\\]\*\*')
|
||||
_double_star_first_before_invalid_regex = re.compile('^\\*\\*[^/]')
|
||||
_double_star_middle_before_invalid_regex = re.compile(r'[^\\]\*\*[^/]')
|
||||
|
||||
|
||||
def _match_component(pattern_component, file_name_component):
|
||||
if len(pattern_component) == 0 and len(file_name_component) == 0:
|
||||
return True
|
||||
elif len(pattern_component) == 0:
|
||||
return False
|
||||
elif len(file_name_component) == 0:
|
||||
return pattern_component == '*'
|
||||
elif pattern_component[0] == '*':
|
||||
return (_match_component(pattern_component, file_name_component[1:]) or
|
||||
_match_component(pattern_component[1:], file_name_component))
|
||||
elif pattern_component[0] == '?':
|
||||
return _match_component(pattern_component[1:], file_name_component[1:])
|
||||
elif pattern_component[0] == '\\':
|
||||
return (len(pattern_component) >= 2 and
|
||||
pattern_component[1] == file_name_component[0] and
|
||||
_match_component(
|
||||
pattern_component[2:], file_name_component[1:]))
|
||||
elif pattern_component[0] != file_name_component[0]:
|
||||
return False
|
||||
else:
|
||||
return _match_component(pattern_component[1:], file_name_component[1:])
|
||||
|
||||
|
||||
def _match_components(pattern_components, file_name_components):
|
||||
if len(pattern_components) == 0 and len(file_name_components) == 0:
|
||||
return True
|
||||
if len(pattern_components) == 0:
|
||||
return False
|
||||
if len(file_name_components) == 0:
|
||||
return len(pattern_components) == 1 and pattern_components[0] == '**'
|
||||
if pattern_components[0] == '**':
|
||||
return (_match_components(pattern_components, file_name_components[1:])
|
||||
or _match_components(
|
||||
pattern_components[1:], file_name_components))
|
||||
else:
|
||||
return (
|
||||
_match_component(
|
||||
pattern_components[0], file_name_components[0]) and
|
||||
_match_components(
|
||||
pattern_components[1:], file_name_components[1:]))
|
||||
|
||||
|
||||
def match(pattern: str, file_name: str):
|
||||
"""Match a glob pattern against a file name.
|
||||
|
||||
Glob pattern matching is for file names, which do not need to exist as
|
||||
files on the file system.
|
||||
|
||||
A file name is a sequence of directory names, possibly followed by the name
|
||||
of a file, with the components separated by a path separator. A glob
|
||||
pattern is similar, except it may contain special characters: A '?' matches
|
||||
any character in a name. A '*' matches any sequence of characters (possibly
|
||||
empty) in a name. Both of these match only within a single component, i.e.,
|
||||
they will not match a path separator. A component in a pattern may also be
|
||||
a literal '**', which matches zero or more components in the complete file
|
||||
name. A backslash '\\' in a pattern acts as an escape character, and
|
||||
indicates that the following character is to be matched literally, even if
|
||||
it is a special character.
|
||||
|
||||
Args:
|
||||
pattern (str): The pattern to match. The path separator in patterns is
|
||||
always '/'.
|
||||
file_name (str): The file name to match against. The path separator in
|
||||
file names is the platform separator
|
||||
|
||||
Returns:
|
||||
bool: True if the pattern matches, False otherwise.
|
||||
"""
|
||||
if (_double_star_after_invalid_regex.search(pattern) is not None or
|
||||
_double_star_first_before_invalid_regex.search(
|
||||
pattern) is not None or
|
||||
_double_star_middle_before_invalid_regex.search(pattern) is not None):
|
||||
raise ValueError(
|
||||
'** in {} not alone between path separators'.format(pattern))
|
||||
|
||||
pattern = pattern.rstrip('/')
|
||||
file_name = file_name.rstrip('/')
|
||||
|
||||
while '**/**' in pattern:
|
||||
pattern = pattern.replace('**/**', '**')
|
||||
|
||||
pattern_components = pattern.split('/')
|
||||
|
||||
# We split on '\' as well as '/' to support unix and windows-style paths
|
||||
file_name_components = re.split(r'[\\/]', file_name)
|
||||
|
||||
return _match_components(pattern_components, file_name_components)
|
26
BaseTools/Plugin/CodeQL/codeqlcli_ext_dep.yaml
Normal file
26
BaseTools/Plugin/CodeQL/codeqlcli_ext_dep.yaml
Normal file
@ -0,0 +1,26 @@
|
||||
## @file codeqlcli_ext_dep.yaml
|
||||
#
|
||||
# Downloads the CodeQL Command-Line Interface (CLI) application that support Linux, Windows, and Mac OS X.
|
||||
#
|
||||
# This download is very large but conveniently provides support for all operating systems. Use it if you
|
||||
# need CodeQL CLI support without concern for the host operating system.
|
||||
#
|
||||
# In an environment where a platform might build in different operating systems, it is recommended to set
|
||||
# the scope for the appropriate CodeQL external dependency based on the host operating system being used.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
{
|
||||
"scope": "codeql-ext-dep",
|
||||
"type": "web",
|
||||
"name": "codeql_cli",
|
||||
"source": "https://github.com/github/codeql-cli-binaries/releases/download/v2.12.4/codeql.zip",
|
||||
"version": "2.12.4",
|
||||
"sha256": "f682f1155d627ad97f10b1bcad97f682011986717bd3823e9cf831ed83ac96e7",
|
||||
"compression_type": "zip",
|
||||
"internal_path": "/codeql/",
|
||||
"flags": ["set_shell_var", ],
|
||||
"var_name": "STUART_CODEQL_PATH"
|
||||
}
|
24
BaseTools/Plugin/CodeQL/codeqlcli_linux_ext_dep.yaml
Normal file
24
BaseTools/Plugin/CodeQL/codeqlcli_linux_ext_dep.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
## @file codeqlcli_linux_ext_dep.yaml
|
||||
#
|
||||
# Downloads the Linux CodeQL Command-Line Interface (CLI) application.
|
||||
#
|
||||
# This download only supports Linux. In an environment where a platform might build in different operating
|
||||
# systems, it is recommended to set the scope for the appropriate CodeQL external dependency based on the
|
||||
# host operating system being used.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
{
|
||||
"scope": "codeql-linux-ext-dep",
|
||||
"type": "web",
|
||||
"name": "codeql_linux_cli",
|
||||
"source": "https://github.com/github/codeql-cli-binaries/releases/download/v2.14.5/codeql-linux64.zip",
|
||||
"version": "2.14.5",
|
||||
"sha256": "72aa5d748ff9ab57cfd86045560683bdc4897e0fe6d9f9a2786d9394674ae733",
|
||||
"compression_type": "zip",
|
||||
"internal_path": "/codeql/",
|
||||
"flags": ["set_shell_var", ],
|
||||
"var_name": "STUART_CODEQL_PATH"
|
||||
}
|
24
BaseTools/Plugin/CodeQL/codeqlcli_windows_ext_dep.yaml
Normal file
24
BaseTools/Plugin/CodeQL/codeqlcli_windows_ext_dep.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
## @file codeqlcli_windows_ext_dep.yaml
|
||||
#
|
||||
# Downloads the Windows CodeQL Command-Line Interface (CLI) application.
|
||||
#
|
||||
# This download only supports Windows. In an environment where a platform might build in different operating
|
||||
# systems, it is recommended to set the scope for the appropriate CodeQL external dependency based on the
|
||||
# host operating system being used.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
{
|
||||
"scope": "codeql-windows-ext-dep",
|
||||
"type": "web",
|
||||
"name": "codeql_windows_cli",
|
||||
"source": "https://github.com/github/codeql-cli-binaries/releases/download/v2.14.5/codeql-win64.zip",
|
||||
"version": "2.14.5",
|
||||
"sha256": "861fcb38365cc311efee0c3a28c77494e93c69a969885b72e53173ad473f61aa",
|
||||
"compression_type": "zip",
|
||||
"internal_path": "/codeql/",
|
||||
"flags": ["set_shell_var", ],
|
||||
"var_name": "STUART_CODEQL_PATH"
|
||||
}
|
0
BaseTools/Plugin/CodeQL/common/__init__.py
Normal file
0
BaseTools/Plugin/CodeQL/common/__init__.py
Normal file
74
BaseTools/Plugin/CodeQL/common/codeql_plugin.py
Normal file
74
BaseTools/Plugin/CodeQL/common/codeql_plugin.py
Normal file
@ -0,0 +1,74 @@
|
||||
# @file codeql_plugin.py
|
||||
#
|
||||
# Common logic shared across the CodeQL plugin.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
import os
|
||||
import shutil
|
||||
from os import PathLike
|
||||
|
||||
from edk2toollib.utility_functions import GetHostInfo
|
||||
|
||||
|
||||
def get_codeql_db_path(workspace: PathLike, package: str, target: str,
|
||||
new_path: bool = True) -> str:
|
||||
"""Return the CodeQL database path for this build.
|
||||
|
||||
Args:
|
||||
workspace (PathLike): The workspace path.
|
||||
package (str): The package name (e.g. "MdeModulePkg")
|
||||
target (str): The target (e.g. "DEBUG")
|
||||
new_path (bool, optional): Whether to create a new database path or
|
||||
return an existing path. Defaults to True.
|
||||
|
||||
Returns:
|
||||
str: The absolute path to the CodeQL database directory.
|
||||
"""
|
||||
codeql_db_dir_name = "codeql-db-" + package + "-" + target
|
||||
codeql_db_dir_name = codeql_db_dir_name.lower()
|
||||
codeql_db_path = os.path.join("Build", codeql_db_dir_name)
|
||||
codeql_db_path = os.path.join(workspace, codeql_db_path)
|
||||
|
||||
i = 0
|
||||
while os.path.isdir(f"{codeql_db_path + '-%s' % i}"):
|
||||
i += 1
|
||||
|
||||
if not new_path:
|
||||
if i == 0:
|
||||
return None
|
||||
else:
|
||||
i -= 1
|
||||
|
||||
return codeql_db_path + f"-{i}"
|
||||
|
||||
|
||||
def get_codeql_cli_path() -> str:
|
||||
"""Return the current CodeQL CLI path.
|
||||
|
||||
Returns:
|
||||
str: The absolute path to the CodeQL CLI application to use for
|
||||
this build.
|
||||
"""
|
||||
# The CodeQL executable path can be passed via the
|
||||
# STUART_CODEQL_PATH environment variable (to override with a
|
||||
# custom value for this run) or read from the system path.
|
||||
codeql_path = None
|
||||
|
||||
if "STUART_CODEQL_PATH" in os.environ:
|
||||
codeql_path = os.environ["STUART_CODEQL_PATH"]
|
||||
|
||||
if GetHostInfo().os == "Windows":
|
||||
codeql_path = os.path.join(codeql_path, "codeql.exe")
|
||||
else:
|
||||
codeql_path = os.path.join(codeql_path, "codeql")
|
||||
|
||||
if not os.path.isfile(codeql_path):
|
||||
codeql_path = None
|
||||
|
||||
if not codeql_path:
|
||||
codeql_path = shutil.which("codeql")
|
||||
|
||||
return codeql_path
|
0
BaseTools/Plugin/CodeQL/integration/__init__.py
Normal file
0
BaseTools/Plugin/CodeQL/integration/__init__.py
Normal file
79
BaseTools/Plugin/CodeQL/integration/stuart_codeql.py
Normal file
79
BaseTools/Plugin/CodeQL/integration/stuart_codeql.py
Normal file
@ -0,0 +1,79 @@
|
||||
# @file stuart_codeql.py
|
||||
#
|
||||
# Exports functions commonly needed for Stuart-based platforms to easily
|
||||
# enable CodeQL in their platform build.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
from edk2toolext.environment.uefi_build import UefiBuilder
|
||||
from edk2toollib.utility_functions import GetHostInfo
|
||||
from argparse import ArgumentParser, Namespace
|
||||
from typing import Tuple
|
||||
|
||||
|
||||
def add_command_line_option(parser: ArgumentParser) -> None:
|
||||
"""Adds the CodeQL command to the platform command line options.
|
||||
|
||||
Args:
|
||||
parser (ArgumentParser): The argument parser used in this build.
|
||||
|
||||
"""
|
||||
parser.add_argument(
|
||||
'--codeql',
|
||||
dest='codeql',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help="Optional - Produces CodeQL results from the build. See "
|
||||
"BaseTools/Plugin/CodeQL/Readme.md for more info.")
|
||||
|
||||
|
||||
def get_scopes(codeql_enabled: bool) -> Tuple[str]:
|
||||
"""Returns the active CodeQL scopes for this build.
|
||||
|
||||
Args:
|
||||
codeql_enabled (bool): Whether CodeQL is enabled.
|
||||
|
||||
Returns:
|
||||
Tuple[str]: A tuple of strings containing scopes that enable the
|
||||
CodeQL plugin.
|
||||
"""
|
||||
active_scopes = ()
|
||||
|
||||
if codeql_enabled:
|
||||
if GetHostInfo().os == "Linux":
|
||||
active_scopes += ("codeql-linux-ext-dep",)
|
||||
else:
|
||||
active_scopes += ("codeql-windows-ext-dep",)
|
||||
active_scopes += ("codeql-build", "codeql-analyze")
|
||||
|
||||
return active_scopes
|
||||
|
||||
|
||||
def is_codeql_enabled_on_command_line(args: Namespace) -> bool:
|
||||
"""Returns whether CodeQL was enabled on the command line.
|
||||
|
||||
Args:
|
||||
args (Namespace): Object holding a string representation of command
|
||||
line arguments.
|
||||
|
||||
Returns:
|
||||
bool: True if CodeQL is enabled on the command line. Otherwise, false.
|
||||
"""
|
||||
return args.codeql
|
||||
|
||||
|
||||
def set_audit_only_mode(uefi_builder: UefiBuilder) -> None:
|
||||
"""Configures the CodeQL plugin to run in audit only mode.
|
||||
|
||||
Args:
|
||||
uefi_builder (UefiBuilder): The UefiBuilder object for this platform
|
||||
build.
|
||||
|
||||
"""
|
||||
|
||||
uefi_builder.env.SetValue(
|
||||
"STUART_CODEQL_AUDIT_ONLY",
|
||||
"true",
|
||||
"Platform Defined")
|
@ -0,0 +1,127 @@
|
||||
# @file DebugMacroCheckBuildPlugin.py
|
||||
#
|
||||
# A build plugin that checks if DEBUG macros are formatted properly.
|
||||
#
|
||||
# In particular, that print format specifiers are defined
|
||||
# with the expected number of arguments in the variable
|
||||
# argument list.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
# Import the build plugin
|
||||
plugin_file = pathlib.Path(__file__)
|
||||
sys.path.append(str(plugin_file.parent.parent))
|
||||
|
||||
# flake8 (E402): Ignore flake8 module level import not at top of file
|
||||
import DebugMacroCheck # noqa: E402
|
||||
|
||||
from edk2toolext import edk2_logging # noqa: E402
|
||||
from edk2toolext.environment.plugintypes.uefi_build_plugin import \
|
||||
IUefiBuildPlugin # noqa: E402
|
||||
from edk2toolext.environment.uefi_build import UefiBuilder # noqa: E402
|
||||
from edk2toollib.uefi.edk2.path_utilities import Edk2Path # noqa: E402
|
||||
from pathlib import Path # noqa: E402
|
||||
|
||||
|
||||
class DebugMacroCheckBuildPlugin(IUefiBuildPlugin):
|
||||
|
||||
def do_pre_build(self, builder: UefiBuilder) -> int:
|
||||
"""Debug Macro Check pre-build functionality.
|
||||
|
||||
The plugin is invoked in pre-build since it can operate independently
|
||||
of build tools and to notify the user of any errors earlier in the
|
||||
build process to reduce feedback time.
|
||||
|
||||
Args:
|
||||
builder (UefiBuilder): A UEFI builder object for this build.
|
||||
|
||||
Returns:
|
||||
int: The number of debug macro errors found. Zero indicates the
|
||||
check either did not run or no errors were found.
|
||||
"""
|
||||
|
||||
# Check if disabled in the environment
|
||||
env_disable = builder.env.GetValue("DISABLE_DEBUG_MACRO_CHECK")
|
||||
if env_disable:
|
||||
return 0
|
||||
|
||||
# Only run on targets with compilation
|
||||
build_target = builder.env.GetValue("TARGET").lower()
|
||||
if "no-target" in build_target:
|
||||
return 0
|
||||
|
||||
edk2 = builder.edk2path
|
||||
package = edk2.GetContainingPackage(
|
||||
builder.edk2path.GetAbsolutePathOnThisSystemFromEdk2RelativePath(
|
||||
builder.env.GetValue("ACTIVE_PLATFORM")
|
||||
)
|
||||
)
|
||||
package_path = Path(
|
||||
edk2.GetAbsolutePathOnThisSystemFromEdk2RelativePath(
|
||||
package))
|
||||
|
||||
# Every debug macro is printed at DEBUG logging level.
|
||||
# Ensure the level is above DEBUG while executing the macro check
|
||||
# plugin to avoid flooding the log handler.
|
||||
handler_level_context = []
|
||||
for h in logging.getLogger().handlers:
|
||||
if h.level < logging.INFO:
|
||||
handler_level_context.append((h, h.level))
|
||||
h.setLevel(logging.INFO)
|
||||
|
||||
edk2_logging.log_progress("Checking DEBUG Macros")
|
||||
|
||||
# There are two ways to specify macro substitution data for this
|
||||
# plugin. If multiple options are present, data is appended from
|
||||
# each option.
|
||||
#
|
||||
# 1. Specify the substitution data in the package CI YAML file.
|
||||
# 2. Specify a standalone substitution data YAML file.
|
||||
##
|
||||
sub_data = {}
|
||||
|
||||
# 1. Allow substitution data to be specified in a "DebugMacroCheck" of
|
||||
# the package CI YAML file. This is used to provide a familiar per-
|
||||
# package customization flow for a package maintainer.
|
||||
package_config_file = Path(
|
||||
os.path.join(
|
||||
package_path, package + ".ci.yaml"))
|
||||
if package_config_file.is_file():
|
||||
with open(package_config_file, 'r') as cf:
|
||||
package_config_file_data = yaml.safe_load(cf)
|
||||
if "DebugMacroCheck" in package_config_file_data and \
|
||||
"StringSubstitutions" in \
|
||||
package_config_file_data["DebugMacroCheck"]:
|
||||
logging.info(f"Loading substitution data in "
|
||||
f"{str(package_config_file)}")
|
||||
sub_data |= package_config_file_data["DebugMacroCheck"]["StringSubstitutions"] # noqa
|
||||
|
||||
# 2. Allow a substitution file to be specified as an environment
|
||||
# variable. This is used to provide flexibility in how to specify a
|
||||
# substitution file. The value can be set anywhere prior to this plugin
|
||||
# getting called such as pre-existing build script.
|
||||
sub_file = builder.env.GetValue("DEBUG_MACRO_CHECK_SUB_FILE")
|
||||
if sub_file:
|
||||
logging.info(f"Loading substitution file {sub_file}")
|
||||
with open(sub_file, 'r') as sf:
|
||||
sub_data |= yaml.safe_load(sf)
|
||||
|
||||
try:
|
||||
error_count = DebugMacroCheck.check_macros_in_directory(
|
||||
package_path,
|
||||
ignore_git_submodules=False,
|
||||
show_progress_bar=False,
|
||||
**sub_data)
|
||||
finally:
|
||||
for h, l in handler_level_context:
|
||||
h.setLevel(l)
|
||||
|
||||
return error_count
|
@ -0,0 +1,11 @@
|
||||
## @file
|
||||
# Build plugin used to check that debug macros are formatted properly.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
{
|
||||
"scope": "global",
|
||||
"name": "Debug Macro Check Plugin",
|
||||
"module": "DebugMacroCheckBuildPlugin"
|
||||
}
|
859
BaseTools/Plugin/DebugMacroCheck/DebugMacroCheck.py
Normal file
859
BaseTools/Plugin/DebugMacroCheck/DebugMacroCheck.py
Normal file
@ -0,0 +1,859 @@
|
||||
# @file DebugMacroCheck.py
|
||||
#
|
||||
# A script that checks if DEBUG macros are formatted properly.
|
||||
#
|
||||
# In particular, that print format specifiers are defined
|
||||
# with the expected number of arguments in the variable
|
||||
# argument list.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
from argparse import RawTextHelpFormatter
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import regex
|
||||
import sys
|
||||
import shutil
|
||||
import timeit
|
||||
import yaml
|
||||
|
||||
from edk2toollib.utility_functions import RunCmd
|
||||
from io import StringIO
|
||||
from pathlib import Path, PurePath
|
||||
from typing import Dict, Iterable, List, Optional, Tuple
|
||||
|
||||
|
||||
PROGRAM_NAME = "Debug Macro Checker"
|
||||
|
||||
|
||||
class GitHelpers:
|
||||
"""
|
||||
Collection of Git helpers.
|
||||
|
||||
Will be moved to a more generic module and imported in the future.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def get_git_ignored_paths(directory_path: PurePath) -> List[Path]:
|
||||
"""Returns ignored files in this git repository.
|
||||
|
||||
Args:
|
||||
directory_path (PurePath): Path to the git directory.
|
||||
|
||||
Returns:
|
||||
List[Path]: List of file absolute paths to all files ignored
|
||||
in this git repository. If git is not found, an empty
|
||||
list will be returned.
|
||||
"""
|
||||
if not shutil.which("git"):
|
||||
logging.warn(
|
||||
"Git is not found on this system. Git submodule paths will "
|
||||
"not be considered.")
|
||||
return []
|
||||
|
||||
out_stream_buffer = StringIO()
|
||||
exit_code = RunCmd("git", "ls-files --other",
|
||||
workingdir=str(directory_path),
|
||||
outstream=out_stream_buffer,
|
||||
logging_level=logging.NOTSET)
|
||||
if exit_code != 0:
|
||||
return []
|
||||
|
||||
rel_paths = out_stream_buffer.getvalue().strip().splitlines()
|
||||
abs_paths = []
|
||||
for path in rel_paths:
|
||||
abs_paths.append(Path(directory_path, path))
|
||||
return abs_paths
|
||||
|
||||
@staticmethod
|
||||
def get_git_submodule_paths(directory_path: PurePath) -> List[Path]:
|
||||
"""Returns submodules in the given workspace directory.
|
||||
|
||||
Args:
|
||||
directory_path (PurePath): Path to the git directory.
|
||||
|
||||
Returns:
|
||||
List[Path]: List of directory absolute paths to the root of
|
||||
each submodule found from this folder. If submodules are not
|
||||
found, an empty list will be returned.
|
||||
"""
|
||||
if not shutil.which("git"):
|
||||
return []
|
||||
|
||||
if os.path.isfile(directory_path.joinpath(".gitmodules")):
|
||||
out_stream_buffer = StringIO()
|
||||
exit_code = RunCmd(
|
||||
"git", "config --file .gitmodules --get-regexp path",
|
||||
workingdir=str(directory_path),
|
||||
outstream=out_stream_buffer,
|
||||
logging_level=logging.NOTSET)
|
||||
if exit_code != 0:
|
||||
return []
|
||||
|
||||
submodule_paths = []
|
||||
for line in out_stream_buffer.getvalue().strip().splitlines():
|
||||
submodule_paths.append(
|
||||
Path(directory_path, line.split()[1]))
|
||||
|
||||
return submodule_paths
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
class QuietFilter(logging.Filter):
|
||||
"""A logging filter that temporarily suppresses message output."""
|
||||
|
||||
def __init__(self, quiet: bool = False):
|
||||
"""Class constructor method.
|
||||
|
||||
Args:
|
||||
quiet (bool, optional): Indicates if messages are currently being
|
||||
printed (False) or not (True). Defaults to False.
|
||||
"""
|
||||
|
||||
self._quiet = quiet
|
||||
|
||||
def filter(self, record: logging.LogRecord) -> bool:
|
||||
"""Quiet filter method.
|
||||
|
||||
Args:
|
||||
record (logging.LogRecord): A log record object that the filter is
|
||||
applied to.
|
||||
|
||||
Returns:
|
||||
bool: True if messages are being suppressed. Otherwise, False.
|
||||
"""
|
||||
return not self._quiet
|
||||
|
||||
|
||||
class ProgressFilter(logging.Filter):
|
||||
"""A logging filter that suppresses 'Progress' messages."""
|
||||
|
||||
def filter(self, record: logging.LogRecord) -> bool:
|
||||
"""Progress filter method.
|
||||
|
||||
Args:
|
||||
record (logging.LogRecord): A log record object that the filter is
|
||||
applied to.
|
||||
|
||||
Returns:
|
||||
bool: True if the message is not a 'Progress' message. Otherwise,
|
||||
False.
|
||||
"""
|
||||
return not record.getMessage().startswith("\rProgress")
|
||||
|
||||
|
||||
class CacheDuringProgressFilter(logging.Filter):
|
||||
"""A logging filter that suppresses messages during progress operations."""
|
||||
|
||||
_message_cache = []
|
||||
|
||||
@property
|
||||
def message_cache(self) -> List[logging.LogRecord]:
|
||||
"""Contains a cache of messages accumulated during time of operation.
|
||||
|
||||
Returns:
|
||||
List[logging.LogRecord]: List of log records stored while the
|
||||
filter was active.
|
||||
"""
|
||||
return self._message_cache
|
||||
|
||||
def filter(self, record: logging.LogRecord):
|
||||
"""Cache progress filter that suppresses messages during progress
|
||||
display output.
|
||||
|
||||
Args:
|
||||
record (logging.LogRecord): A log record to cache.
|
||||
"""
|
||||
self._message_cache.append(record)
|
||||
|
||||
|
||||
def check_debug_macros(macros: Iterable[Dict[str, str]],
|
||||
file_dbg_path: str,
|
||||
**macro_subs: str
|
||||
) -> Tuple[int, int, int]:
|
||||
"""Checks if debug macros contain formatting errors.
|
||||
|
||||
Args:
|
||||
macros (Iterable[Dict[str, str]]): : A groupdict of macro matches.
|
||||
This is an iterable of dictionaries with group names from the regex
|
||||
match as the key and the matched string as the value for the key.
|
||||
|
||||
file_dbg_path (str): The file path (or other custom string) to display
|
||||
in debug messages.
|
||||
|
||||
macro_subs (Dict[str,str]): Variable-length keyword and replacement
|
||||
value string pairs to substitute during debug macro checks.
|
||||
|
||||
Returns:
|
||||
Tuple[int, int, int]: A tuple of the number of formatting errors,
|
||||
number of print specifiers, and number of arguments for the macros
|
||||
given.
|
||||
"""
|
||||
|
||||
macro_subs = {k.lower(): v for k, v in macro_subs.items()}
|
||||
|
||||
arg_cnt, failure_cnt, print_spec_cnt = 0, 0, 0
|
||||
for macro in macros:
|
||||
# Special Specifier Handling
|
||||
processed_dbg_str = macro['dbg_str'].strip().lower()
|
||||
|
||||
logging.debug(f"Inspecting macro: {macro}")
|
||||
|
||||
# Make any macro substitutions so further processing is applied
|
||||
# to the substituted value.
|
||||
for k in macro_subs.keys():
|
||||
processed_dbg_str = processed_dbg_str.replace(k, macro_subs[k])
|
||||
|
||||
logging.debug("Debug macro string after replacements: "
|
||||
f"{processed_dbg_str}")
|
||||
|
||||
# These are very rarely used in debug strings. They are somewhat
|
||||
# more common in HII code to control text displayed on the
|
||||
# console. Due to the rarity and likelihood usage is a mistake,
|
||||
# a warning is shown if found.
|
||||
specifier_display_replacements = ['%n', '%h', '%e', '%b', '%v']
|
||||
for s in specifier_display_replacements:
|
||||
if s in processed_dbg_str:
|
||||
logging.warning(f"File: {file_dbg_path}")
|
||||
logging.warning(f" {s} found in string and ignored:")
|
||||
logging.warning(f" \"{processed_dbg_str}\"")
|
||||
processed_dbg_str = processed_dbg_str.replace(s, '')
|
||||
|
||||
# These are miscellaneous print specifiers that do not require
|
||||
# special parsing and simply need to be replaced since they do
|
||||
# have a corresponding argument associated with them.
|
||||
specifier_other_replacements = ['%%', '\r', '\n']
|
||||
for s in specifier_other_replacements:
|
||||
if s in processed_dbg_str:
|
||||
processed_dbg_str = processed_dbg_str.replace(s, '')
|
||||
|
||||
processed_dbg_str = re.sub(
|
||||
r'%[.\-+ ,Ll0-9]*\*[.\-+ ,Ll0-9]*[a-zA-Z]', '%_%_',
|
||||
processed_dbg_str)
|
||||
logging.debug(f"Final macro before print specifier scan: "
|
||||
f"{processed_dbg_str}")
|
||||
|
||||
print_spec_cnt = processed_dbg_str.count('%')
|
||||
|
||||
# Need to take into account parentheses between args in function
|
||||
# calls that might be in the args list. Use regex module for
|
||||
# this one since the recursive pattern match helps simplify
|
||||
# only matching commas outside nested call groups.
|
||||
if macro['dbg_args'] is None:
|
||||
processed_arg_str = ""
|
||||
else:
|
||||
processed_arg_str = macro['dbg_args'].strip()
|
||||
|
||||
argument_other_replacements = ['\r', '\n']
|
||||
for r in argument_other_replacements:
|
||||
if s in processed_arg_str:
|
||||
processed_arg_str = processed_arg_str.replace(s, '')
|
||||
processed_arg_str = re.sub(r' +', ' ', processed_arg_str)
|
||||
|
||||
# Handle special case of commas in arg strings - remove them for
|
||||
# final count to pick up correct number of argument separating
|
||||
# commas.
|
||||
processed_arg_str = re.sub(
|
||||
r'([\"\'])(?:|\\.|[^\\])*?(\1)',
|
||||
'',
|
||||
processed_arg_str)
|
||||
|
||||
arg_matches = regex.findall(
|
||||
r'(?:\((?:[^)(]+|(?R))*+\))|(,)',
|
||||
processed_arg_str,
|
||||
regex.MULTILINE)
|
||||
|
||||
arg_cnt = 0
|
||||
if processed_arg_str != '':
|
||||
arg_cnt = arg_matches.count(',')
|
||||
|
||||
if print_spec_cnt != arg_cnt:
|
||||
logging.error(f"File: {file_dbg_path}")
|
||||
logging.error(f" Message = {macro['dbg_str']}")
|
||||
logging.error(f" Arguments = \"{processed_arg_str}\"")
|
||||
logging.error(f" Specifier Count = {print_spec_cnt}")
|
||||
logging.error(f" Argument Count = {arg_cnt}")
|
||||
|
||||
failure_cnt += 1
|
||||
|
||||
return failure_cnt, print_spec_cnt, arg_cnt
|
||||
|
||||
|
||||
def get_debug_macros(file_contents: str) -> List[Dict[str, str]]:
|
||||
"""Extract debug macros from the given file contents.
|
||||
|
||||
Args:
|
||||
file_contents (str): A string of source file contents that may
|
||||
contain debug macros.
|
||||
|
||||
Returns:
|
||||
List[Dict[str, str]]: A groupdict of debug macro regex matches
|
||||
within the file contents provided.
|
||||
"""
|
||||
|
||||
# This is the main regular expression that is responsible for identifying
|
||||
# DEBUG macros within source files and grouping the macro message string
|
||||
# and macro arguments strings so they can be further processed.
|
||||
r = regex.compile(
|
||||
r'(?>(?P<prologue>DEBUG\s*\(\s*\((?:.*?,))(?:\s*))(?P<dbg_str>.*?(?:\"'
|
||||
r'(?:[^\"\\]|\\.)*\".*?)*)(?:(?(?=,)(?<dbg_args>.*?(?=(?:\s*\)){2}\s*;'
|
||||
r'))))(?:\s*\)){2,};?',
|
||||
regex.MULTILINE | regex.DOTALL)
|
||||
return [m.groupdict() for m in r.finditer(file_contents)]
|
||||
|
||||
|
||||
def check_macros_in_string(src_str: str,
|
||||
file_dbg_path: str,
|
||||
**macro_subs: str) -> Tuple[int, int, int]:
|
||||
"""Checks for debug macro formatting errors in a string.
|
||||
|
||||
Args:
|
||||
src_str (str): Contents of the string with debug macros.
|
||||
|
||||
file_dbg_path (str): The file path (or other custom string) to display
|
||||
in debug messages.
|
||||
|
||||
macro_subs (Dict[str,str]): Variable-length keyword and replacement
|
||||
value string pairs to substitute during debug macro checks.
|
||||
|
||||
Returns:
|
||||
Tuple[int, int, int]: A tuple of the number of formatting errors,
|
||||
number of print specifiers, and number of arguments for the macros
|
||||
in the string given.
|
||||
"""
|
||||
return check_debug_macros(
|
||||
get_debug_macros(src_str), file_dbg_path, **macro_subs)
|
||||
|
||||
|
||||
def check_macros_in_file(file: PurePath,
|
||||
file_dbg_path: str,
|
||||
show_utf8_decode_warning: bool = False,
|
||||
**macro_subs: str) -> Tuple[int, int, int]:
|
||||
"""Checks for debug macro formatting errors in a file.
|
||||
|
||||
Args:
|
||||
file (PurePath): The file path to check.
|
||||
|
||||
file_dbg_path (str): The file path (or other custom string) to display
|
||||
in debug messages.
|
||||
|
||||
show_utf8_decode_warning (bool, optional): Indicates whether to show
|
||||
warnings if UTF-8 files fail to decode. Defaults to False.
|
||||
|
||||
macro_subs (Dict[str,str]): Variable-length keyword and replacement
|
||||
value string pairs to substitute during debug macro checks.
|
||||
|
||||
Returns:
|
||||
Tuple[int, int, int]: A tuple of the number of formatting errors,
|
||||
number of print specifiers, and number of arguments for the macros
|
||||
in the file given.
|
||||
"""
|
||||
try:
|
||||
return check_macros_in_string(
|
||||
file.read_text(encoding='utf-8'), file_dbg_path,
|
||||
**macro_subs)
|
||||
except UnicodeDecodeError as e:
|
||||
if show_utf8_decode_warning:
|
||||
logging.warning(
|
||||
f"{file_dbg_path} UTF-8 decode error.\n"
|
||||
" Debug macro code check skipped!\n"
|
||||
f" -> {str(e)}")
|
||||
return 0, 0, 0
|
||||
|
||||
|
||||
def check_macros_in_directory(directory: PurePath,
|
||||
file_extensions: Iterable[str] = ('.c',),
|
||||
ignore_git_ignore_files: Optional[bool] = True,
|
||||
ignore_git_submodules: Optional[bool] = True,
|
||||
show_progress_bar: Optional[bool] = True,
|
||||
show_utf8_decode_warning: bool = False,
|
||||
**macro_subs: str
|
||||
) -> int:
|
||||
"""Checks files with the given extension in the given directory for debug
|
||||
macro formatting errors.
|
||||
|
||||
Args:
|
||||
directory (PurePath): The path to the directory to check.
|
||||
file_extensions (Iterable[str], optional): An iterable of strings
|
||||
representing file extensions to check. Defaults to ('.c',).
|
||||
|
||||
ignore_git_ignore_files (Optional[bool], optional): Indicates whether
|
||||
files ignored by git should be ignored for the debug macro check.
|
||||
Defaults to True.
|
||||
|
||||
ignore_git_submodules (Optional[bool], optional): Indicates whether
|
||||
files located in git submodules should not be checked. Defaults to
|
||||
True.
|
||||
|
||||
show_progress_bar (Optional[bool], optional): Indicates whether to
|
||||
show a progress bar to show progress status while checking macros.
|
||||
This is more useful on a very large directories. Defaults to True.
|
||||
|
||||
show_utf8_decode_warning (bool, optional): Indicates whether to show
|
||||
warnings if UTF-8 files fail to decode. Defaults to False.
|
||||
|
||||
macro_subs (Dict[str,str]): Variable-length keyword and replacement
|
||||
value string pairs to substitute during debug macro checks.
|
||||
|
||||
Returns:
|
||||
int: Count of debug macro errors in the directory.
|
||||
"""
|
||||
def _get_file_list(root_directory: PurePath,
|
||||
extensions: Iterable[str]) -> List[Path]:
|
||||
"""Returns a list of files recursively located within the path.
|
||||
|
||||
Args:
|
||||
root_directory (PurePath): A directory Path object to the root
|
||||
folder.
|
||||
|
||||
extensions (Iterable[str]): An iterable of strings that
|
||||
represent file extensions to recursively search for within
|
||||
root_directory.
|
||||
|
||||
Returns:
|
||||
List[Path]: List of file Path objects to files found in the
|
||||
given directory with the given extensions.
|
||||
"""
|
||||
def _show_file_discovered_message(file_count: int,
|
||||
elapsed_time: float) -> None:
|
||||
print(f"\rDiscovered {file_count:,} files in",
|
||||
f"{current_start_delta:-.0f}s"
|
||||
f"{'.' * min(int(current_start_delta), 40)}", end="\r")
|
||||
|
||||
start_time = timeit.default_timer()
|
||||
previous_indicator_time = start_time
|
||||
|
||||
files = []
|
||||
for file in root_directory.rglob('*'):
|
||||
if file.suffix in extensions:
|
||||
files.append(Path(file))
|
||||
|
||||
# Give an indicator progress is being made
|
||||
# This has a negligible impact on overall performance
|
||||
# with print emission limited to half second intervals.
|
||||
current_time = timeit.default_timer()
|
||||
current_start_delta = current_time - start_time
|
||||
|
||||
if current_time - previous_indicator_time >= 0.5:
|
||||
# Since this rewrites the line, it can be considered a form
|
||||
# of progress bar
|
||||
if show_progress_bar:
|
||||
_show_file_discovered_message(len(files),
|
||||
current_start_delta)
|
||||
previous_indicator_time = current_time
|
||||
|
||||
if show_progress_bar:
|
||||
_show_file_discovered_message(len(files), current_start_delta)
|
||||
print()
|
||||
|
||||
return files
|
||||
|
||||
logging.info(f"Checking Debug Macros in directory: "
|
||||
f"{directory.resolve()}\n")
|
||||
|
||||
logging.info("Gathering the overall file list. This might take a"
|
||||
"while.\n")
|
||||
|
||||
start_time = timeit.default_timer()
|
||||
file_list = set(_get_file_list(directory, file_extensions))
|
||||
end_time = timeit.default_timer() - start_time
|
||||
|
||||
logging.debug(f"[PERF] File search found {len(file_list):,} files in "
|
||||
f"{end_time:.2f} seconds.")
|
||||
|
||||
if ignore_git_ignore_files:
|
||||
logging.info("Getting git ignore files...")
|
||||
start_time = timeit.default_timer()
|
||||
ignored_file_paths = GitHelpers.get_git_ignored_paths(directory)
|
||||
end_time = timeit.default_timer() - start_time
|
||||
|
||||
logging.debug(f"[PERF] File ignore gathering took {end_time:.2f} "
|
||||
f"seconds.")
|
||||
|
||||
logging.info("Ignoring git ignore files...")
|
||||
logging.debug(f"File list count before git ignore {len(file_list):,}")
|
||||
start_time = timeit.default_timer()
|
||||
file_list = file_list.difference(ignored_file_paths)
|
||||
end_time = timeit.default_timer() - start_time
|
||||
logging.info(f" {len(ignored_file_paths):,} files are ignored by git")
|
||||
logging.info(f" {len(file_list):,} files after removing "
|
||||
f"ignored files")
|
||||
|
||||
logging.debug(f"[PERF] File ignore calculation took {end_time:.2f} "
|
||||
f"seconds.")
|
||||
|
||||
if ignore_git_submodules:
|
||||
logging.info("Ignoring git submodules...")
|
||||
submodule_paths = GitHelpers.get_git_submodule_paths(directory)
|
||||
if submodule_paths:
|
||||
logging.debug(f"File list count before git submodule exclusion "
|
||||
f"{len(file_list):,}")
|
||||
start_time = timeit.default_timer()
|
||||
file_list = [f for f in file_list
|
||||
if not f.is_relative_to(*submodule_paths)]
|
||||
end_time = timeit.default_timer() - start_time
|
||||
|
||||
for path in enumerate(submodule_paths):
|
||||
logging.debug(" {0}. {1}".format(*path))
|
||||
|
||||
logging.info(f" {len(submodule_paths):,} submodules found")
|
||||
logging.info(f" {len(file_list):,} files will be examined after "
|
||||
f"excluding files in submodules")
|
||||
|
||||
logging.debug(f"[PERF] Submodule exclusion calculation took "
|
||||
f"{end_time:.2f} seconds.")
|
||||
else:
|
||||
logging.warning("No submodules found")
|
||||
|
||||
logging.info(f"\nStarting macro check on {len(file_list):,} files.")
|
||||
|
||||
cache_progress_filter = CacheDuringProgressFilter()
|
||||
handler = next((h for h in logging.getLogger().handlers if h.get_name() ==
|
||||
'stdout_logger_handler'), None)
|
||||
|
||||
if handler is not None:
|
||||
handler.addFilter(cache_progress_filter)
|
||||
|
||||
start_time = timeit.default_timer()
|
||||
|
||||
failure_cnt, file_cnt = 0, 0
|
||||
for file_cnt, file in enumerate(file_list):
|
||||
file_rel_path = str(file.relative_to(directory))
|
||||
failure_cnt += check_macros_in_file(
|
||||
file, file_rel_path, show_utf8_decode_warning,
|
||||
**macro_subs)[0]
|
||||
if show_progress_bar:
|
||||
_show_progress(file_cnt, len(file_list),
|
||||
f" {failure_cnt} errors" if failure_cnt > 0 else "")
|
||||
|
||||
if show_progress_bar:
|
||||
_show_progress(len(file_list), len(file_list),
|
||||
f" {failure_cnt} errors" if failure_cnt > 0 else "")
|
||||
print("\n", flush=True)
|
||||
|
||||
end_time = timeit.default_timer() - start_time
|
||||
|
||||
if handler is not None:
|
||||
handler.removeFilter(cache_progress_filter)
|
||||
|
||||
for record in cache_progress_filter.message_cache:
|
||||
handler.emit(record)
|
||||
|
||||
logging.debug(f"[PERF] The macro check operation took {end_time:.2f} "
|
||||
f"seconds.")
|
||||
|
||||
_log_failure_count(failure_cnt, file_cnt)
|
||||
|
||||
return failure_cnt
|
||||
|
||||
|
||||
def _log_failure_count(failure_count: int, file_count: int) -> None:
|
||||
"""Logs the failure count.
|
||||
|
||||
Args:
|
||||
failure_count (int): Count of failures to log.
|
||||
|
||||
file_count (int): Count of files with failures.
|
||||
"""
|
||||
if failure_count > 0:
|
||||
logging.error("\n")
|
||||
logging.error(f"{failure_count:,} debug macro errors in "
|
||||
f"{file_count:,} files")
|
||||
|
||||
|
||||
def _show_progress(step: int, total: int, suffix: str = '') -> None:
|
||||
"""Print progress of tick to total.
|
||||
|
||||
Args:
|
||||
step (int): The current step count.
|
||||
|
||||
total (int): The total step count.
|
||||
|
||||
suffix (str): String to print at the end of the progress bar.
|
||||
"""
|
||||
global _progress_start_time
|
||||
|
||||
if step == 0:
|
||||
_progress_start_time = timeit.default_timer()
|
||||
|
||||
terminal_col = shutil.get_terminal_size().columns
|
||||
var_consume_len = (len("Progress|\u2588| 000.0% Complete 000s") +
|
||||
len(suffix))
|
||||
avail_len = terminal_col - var_consume_len
|
||||
|
||||
percent = f"{100 * (step / float(total)):3.1f}"
|
||||
filled = int(avail_len * step // total)
|
||||
bar = '\u2588' * filled + '-' * (avail_len - filled)
|
||||
step_time = timeit.default_timer() - _progress_start_time
|
||||
|
||||
print(f'\rProgress|{bar}| {percent}% Complete {step_time:-3.0f}s'
|
||||
f'{suffix}', end='\r')
|
||||
|
||||
|
||||
def _module_invocation_check_macros_in_directory_wrapper() -> int:
|
||||
"""Provides an command-line argument wrapper for checking debug macros.
|
||||
|
||||
Returns:
|
||||
int: The system exit code value.
|
||||
"""
|
||||
import argparse
|
||||
import builtins
|
||||
|
||||
def _check_dir_path(dir_path: str) -> bool:
|
||||
"""Returns the absolute path if the path is a directory."
|
||||
|
||||
Args:
|
||||
dir_path (str): A directory file system path.
|
||||
|
||||
Raises:
|
||||
NotADirectoryError: The directory path given is not a directory.
|
||||
|
||||
Returns:
|
||||
bool: True if the path is a directory else False.
|
||||
"""
|
||||
abs_dir_path = os.path.abspath(dir_path)
|
||||
if os.path.isdir(dir_path):
|
||||
return abs_dir_path
|
||||
else:
|
||||
raise NotADirectoryError(abs_dir_path)
|
||||
|
||||
def _check_file_path(file_path: str) -> bool:
|
||||
"""Returns the absolute path if the path is a file."
|
||||
|
||||
Args:
|
||||
file_path (str): A file path.
|
||||
|
||||
Raises:
|
||||
FileExistsError: The path is not a valid file.
|
||||
|
||||
Returns:
|
||||
bool: True if the path is a valid file else False.
|
||||
"""
|
||||
abs_file_path = os.path.abspath(file_path)
|
||||
if os.path.isfile(file_path):
|
||||
return abs_file_path
|
||||
else:
|
||||
raise FileExistsError(file_path)
|
||||
|
||||
def _quiet_print(*args, **kwargs):
|
||||
"""Replaces print when quiet is requested to prevent printing messages.
|
||||
"""
|
||||
pass
|
||||
|
||||
root_logger = logging.getLogger()
|
||||
root_logger.setLevel(logging.DEBUG)
|
||||
|
||||
stdout_logger_handler = logging.StreamHandler(sys.stdout)
|
||||
stdout_logger_handler.set_name('stdout_logger_handler')
|
||||
stdout_logger_handler.setLevel(logging.INFO)
|
||||
stdout_logger_handler.setFormatter(logging.Formatter('%(message)s'))
|
||||
root_logger.addHandler(stdout_logger_handler)
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
prog=PROGRAM_NAME,
|
||||
description=(
|
||||
"Checks for debug macro formatting "
|
||||
"errors within files recursively located within "
|
||||
"a given directory."),
|
||||
formatter_class=RawTextHelpFormatter)
|
||||
|
||||
io_req_group = parser.add_mutually_exclusive_group(required=True)
|
||||
io_opt_group = parser.add_argument_group(
|
||||
"Optional input and output")
|
||||
git_group = parser.add_argument_group("Optional git control")
|
||||
|
||||
io_req_group.add_argument('-w', '--workspace-directory',
|
||||
type=_check_dir_path,
|
||||
help="Directory of source files to check.\n\n")
|
||||
|
||||
io_req_group.add_argument('-i', '--input-file', nargs='?',
|
||||
type=_check_file_path,
|
||||
help="File path for an input file to check.\n\n"
|
||||
"Note that some other options do not apply "
|
||||
"if a single file is specified such as "
|
||||
"the\ngit options and file extensions.\n\n")
|
||||
|
||||
io_opt_group.add_argument('-l', '--log-file',
|
||||
nargs='?',
|
||||
default=None,
|
||||
const='debug_macro_check.log',
|
||||
help="File path for log output.\n"
|
||||
"(default: if the flag is given with no "
|
||||
"file path then a file called\n"
|
||||
"debug_macro_check.log is created and used "
|
||||
"in the current directory)\n\n")
|
||||
|
||||
io_opt_group.add_argument('-s', '--substitution-file',
|
||||
type=_check_file_path,
|
||||
help="A substitution YAML file specifies string "
|
||||
"substitutions to perform within the debug "
|
||||
"macro.\n\nThis is intended to be a simple "
|
||||
"mechanism to expand the rare cases of pre-"
|
||||
"processor\nmacros without directly "
|
||||
"involving the pre-processor. The file "
|
||||
"consists of one or more\nstring value "
|
||||
"pairs where the key is the identifier to "
|
||||
"replace and the value is the value\nto "
|
||||
"replace it with.\n\nThis can also be used "
|
||||
"as a method to ignore results by "
|
||||
"replacing the problematic string\nwith a "
|
||||
"different string.\n\n")
|
||||
|
||||
io_opt_group.add_argument('-v', '--verbose-log-file',
|
||||
action='count',
|
||||
default=0,
|
||||
help="Set file logging verbosity level.\n"
|
||||
" - None: Info & > level messages\n"
|
||||
" - '-v': + Debug level messages\n"
|
||||
" - '-vv': + File name and function\n"
|
||||
" - '-vvv': + Line number\n"
|
||||
" - '-vvvv': + Timestamp\n"
|
||||
"(default: verbose logging is not enabled)"
|
||||
"\n\n")
|
||||
|
||||
io_opt_group.add_argument('-n', '--no-progress-bar', action='store_true',
|
||||
help="Disables progress bars.\n"
|
||||
"(default: progress bars are used in some"
|
||||
"places to show progress)\n\n")
|
||||
|
||||
io_opt_group.add_argument('-q', '--quiet', action='store_true',
|
||||
help="Disables console output.\n"
|
||||
"(default: console output is enabled)\n\n")
|
||||
|
||||
io_opt_group.add_argument('-u', '--utf8w', action='store_true',
|
||||
help="Shows warnings for file UTF-8 decode "
|
||||
"errors.\n"
|
||||
"(default: UTF-8 decode errors are not "
|
||||
"shown)\n\n")
|
||||
|
||||
git_group.add_argument('-df', '--do-not-ignore-git-ignore-files',
|
||||
action='store_true',
|
||||
help="Do not ignore git ignored files.\n"
|
||||
"(default: files in git ignore files are "
|
||||
"ignored)\n\n")
|
||||
|
||||
git_group.add_argument('-ds', '--do-not-ignore-git_submodules',
|
||||
action='store_true',
|
||||
help="Do not ignore files in git submodules.\n"
|
||||
"(default: files in git submodules are "
|
||||
"ignored)\n\n")
|
||||
|
||||
parser.add_argument('-e', '--extensions', nargs='*', default=['.c'],
|
||||
help="List of file extensions to include.\n"
|
||||
"(default: %(default)s)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.quiet:
|
||||
# Don't print in the few places that directly print
|
||||
builtins.print = _quiet_print
|
||||
stdout_logger_handler.addFilter(QuietFilter(args.quiet))
|
||||
|
||||
if args.log_file:
|
||||
file_logger_handler = logging.FileHandler(filename=args.log_file,
|
||||
mode='w', encoding='utf-8')
|
||||
|
||||
# In an ideal world, everyone would update to the latest Python
|
||||
# minor version (3.10) after a few weeks/months. Since that's not the
|
||||
# case, resist from using structural pattern matching in Python 3.10.
|
||||
# https://peps.python.org/pep-0636/
|
||||
|
||||
if args.verbose_log_file == 0:
|
||||
file_logger_handler.setLevel(logging.INFO)
|
||||
file_logger_formatter = logging.Formatter(
|
||||
'%(levelname)-8s %(message)s')
|
||||
elif args.verbose_log_file == 1:
|
||||
file_logger_handler.setLevel(logging.DEBUG)
|
||||
file_logger_formatter = logging.Formatter(
|
||||
'%(levelname)-8s %(message)s')
|
||||
elif args.verbose_log_file == 2:
|
||||
file_logger_handler.setLevel(logging.DEBUG)
|
||||
file_logger_formatter = logging.Formatter(
|
||||
'[%(filename)s - %(funcName)20s() ] %(levelname)-8s '
|
||||
'%(message)s')
|
||||
elif args.verbose_log_file == 3:
|
||||
file_logger_handler.setLevel(logging.DEBUG)
|
||||
file_logger_formatter = logging.Formatter(
|
||||
'[%(filename)s:%(lineno)s - %(funcName)20s() ] '
|
||||
'%(levelname)-8s %(message)s')
|
||||
elif args.verbose_log_file == 4:
|
||||
file_logger_handler.setLevel(logging.DEBUG)
|
||||
file_logger_formatter = logging.Formatter(
|
||||
'%(asctime)s [%(filename)s:%(lineno)s - %(funcName)20s() ]'
|
||||
' %(levelname)-8s %(message)s')
|
||||
else:
|
||||
file_logger_handler.setLevel(logging.DEBUG)
|
||||
file_logger_formatter = logging.Formatter(
|
||||
'%(asctime)s [%(filename)s:%(lineno)s - %(funcName)20s() ]'
|
||||
' %(levelname)-8s %(message)s')
|
||||
|
||||
file_logger_handler.addFilter(ProgressFilter())
|
||||
file_logger_handler.setFormatter(file_logger_formatter)
|
||||
root_logger.addHandler(file_logger_handler)
|
||||
|
||||
logging.info(PROGRAM_NAME + "\n")
|
||||
|
||||
substitution_data = {}
|
||||
if args.substitution_file:
|
||||
logging.info(f"Loading substitution file {args.substitution_file}")
|
||||
with open(args.substitution_file, 'r') as sf:
|
||||
substitution_data = yaml.safe_load(sf)
|
||||
|
||||
if args.workspace_directory:
|
||||
return check_macros_in_directory(
|
||||
Path(args.workspace_directory),
|
||||
args.extensions,
|
||||
not args.do_not_ignore_git_ignore_files,
|
||||
not args.do_not_ignore_git_submodules,
|
||||
not args.no_progress_bar,
|
||||
args.utf8w,
|
||||
**substitution_data)
|
||||
else:
|
||||
curr_dir = Path(__file__).parent
|
||||
input_file = Path(args.input_file)
|
||||
|
||||
rel_path = str(input_file)
|
||||
if input_file.is_relative_to(curr_dir):
|
||||
rel_path = str(input_file.relative_to(curr_dir))
|
||||
|
||||
logging.info(f"Checking Debug Macros in File: "
|
||||
f"{input_file.resolve()}\n")
|
||||
|
||||
start_time = timeit.default_timer()
|
||||
failure_cnt = check_macros_in_file(
|
||||
input_file,
|
||||
rel_path,
|
||||
args.utf8w,
|
||||
**substitution_data)[0]
|
||||
end_time = timeit.default_timer() - start_time
|
||||
|
||||
logging.debug(f"[PERF] The file macro check operation took "
|
||||
f"{end_time:.2f} seconds.")
|
||||
|
||||
_log_failure_count(failure_cnt, 1)
|
||||
|
||||
return failure_cnt
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# The exit status value is the number of macro formatting errors found.
|
||||
# Therefore, if no macro formatting errors are found, 0 is returned.
|
||||
# Some systems require the return value to be in the range 0-127, so
|
||||
# a lower maximum of 100 is enforced to allow a wide range of potential
|
||||
# values with a reasonably large maximum.
|
||||
try:
|
||||
sys.exit(max(_module_invocation_check_macros_in_directory_wrapper(),
|
||||
100))
|
||||
except KeyboardInterrupt:
|
||||
logging.warning("Exiting due to keyboard interrupt.")
|
||||
# Actual formatting errors are only allowed to reach 100.
|
||||
# 101 signals a keyboard interrupt.
|
||||
sys.exit(101)
|
||||
except FileExistsError as e:
|
||||
# 102 signals a file not found error.
|
||||
logging.critical(f"Input file {e.args[0]} does not exist.")
|
||||
sys.exit(102)
|
253
BaseTools/Plugin/DebugMacroCheck/Readme.md
Normal file
253
BaseTools/Plugin/DebugMacroCheck/Readme.md
Normal file
@ -0,0 +1,253 @@
|
||||
# Debug Macro Check
|
||||
|
||||
This Python application scans all files in a build package for debug macro formatting issues. It is intended to be a
|
||||
fundamental build-time check that is part of a normal developer build process to catch errors right away.
|
||||
|
||||
As a build plugin, it is capable of finding these errors early in the development process after code is initially
|
||||
written to ensure that all code tested is free of debug macro formatting errors. These errors often creep into debug
|
||||
prints in error conditions that are not frequently executed making debug even more difficult and confusing when they
|
||||
are encountered. In other cases, debug macros with these errors in the main code path can lead to unexpected behavior
|
||||
when executed. As a standalone script, it can be easily run manually or integrated into other CI processes.
|
||||
|
||||
The plugin is part of a set of debug macro check scripts meant to be relatively portable so they can be applied to
|
||||
additional code bases with minimal effort.
|
||||
|
||||
## 1. BuildPlugin/DebugMacroCheckBuildPlugin.py
|
||||
|
||||
This is the build plugin. It is discovered within the Stuart Self-Describing Environment (SDE) due to the accompanying
|
||||
file `DebugMacroCheck_plugin_in.yaml`.
|
||||
|
||||
Since macro errors are considered a coding bug that should be found and fixed during the build phase of the developer
|
||||
process (before debug and testing), this plugin is run in pre-build. It will run within the scope of the package
|
||||
being compiled. For a platform build, this means it will run against the package being built. In a CI build, it will
|
||||
run in pre-build for each package as each package is built.
|
||||
|
||||
The build plugin has the following attributes:
|
||||
|
||||
1. Registered at `global` scope. This means it will always run.
|
||||
|
||||
2. Called only on compilable build targets (i.e. does nothing on `"NO-TARGET"`).
|
||||
|
||||
3. Runs as a pre-build step. This means it gives results right away to ensure compilation follows on a clean slate.
|
||||
This also means it runs in platform build and CI. It is run in CI as a pre-build step when the `CompilerPlugin`
|
||||
compiles code. This ensures even if the plugin was not run locally, all code submissions have been checked.
|
||||
|
||||
4. Reports any errors in the build log and fails the build upon error making it easy to discover problems.
|
||||
|
||||
5. Supports two methods of configuration via "substitution strings":
|
||||
|
||||
1. By setting a build variable called `DEBUG_MACRO_CHECK_SUB_FILE` with the name of a substitution YAML file to
|
||||
use.
|
||||
|
||||
**Example:**
|
||||
|
||||
```python
|
||||
shell_environment.GetBuildVars().SetValue(
|
||||
"DEBUG_MACRO_CHECK_SUB_FILE",
|
||||
os.path.join(self.GetWorkspaceRoot(), "DebugMacroCheckSub.yaml"),
|
||||
"Set in CISettings.py")
|
||||
```
|
||||
|
||||
**Substitution File Content Example:**
|
||||
|
||||
```yaml
|
||||
---
|
||||
# OvmfPkg/CpuHotplugSmm/ApicId.h
|
||||
# Reason: Substitute with macro value
|
||||
FMT_APIC_ID: 0x%08x
|
||||
|
||||
# DynamicTablesPkg/Include/ConfigurationManagerObject.h
|
||||
# Reason: Substitute with macro value
|
||||
FMT_CM_OBJECT_ID: 0x%lx
|
||||
|
||||
# OvmfPkg/IntelTdx/TdTcg2Dxe/TdTcg2Dxe.c
|
||||
# Reason: Acknowledging use of two format specifiers in string with one argument
|
||||
# Replace ternary operator in debug string with single specifier
|
||||
'Index == COLUME_SIZE/2 ? " | %02x" : " %02x"': "%d"
|
||||
|
||||
# DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
|
||||
# ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c
|
||||
# Reason: Acknowledge that string *should* expand to one specifier
|
||||
# Replace variable with expected number of specifiers (1)
|
||||
Parser[Index].Format: "%d"
|
||||
```
|
||||
|
||||
2. By entering the string substitutions directory into a dictionary called `StringSubstitutions` in a
|
||||
`DebugMacroCheck` section of the package CI YAML file.
|
||||
|
||||
**Example:**
|
||||
|
||||
```yaml
|
||||
"DebugMacroCheck": {
|
||||
"StringSubstitutions": {
|
||||
"SUB_A": "%Lx"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Debug Macro Check Build Plugin: Simple Disable
|
||||
|
||||
The build plugin can simply be disabled by setting an environment variable named `"DISABLE_DEBUG_MACRO_CHECK"`. The
|
||||
plugin is disabled on existence of the variable. The contents of the variable are not inspected at this time.
|
||||
|
||||
## 2. DebugMacroCheck.py
|
||||
|
||||
This is the main Python module containing the implementation logic. The build plugin simply wraps around it.
|
||||
|
||||
When first running debug macro check against a new, large code base, it is recommended to first run this standalone
|
||||
script and address all of the issues and then enable the build plugin.
|
||||
|
||||
The module supports a number of configuration parameters to ease debug of errors and to provide flexibility for
|
||||
different build environments.
|
||||
|
||||
### EDK 2 PyTool Library Dependency
|
||||
|
||||
This script has minimal library dependencies. However, it has one dependency you might not be familiar with on the
|
||||
Tianocore EDK 2 PyTool Library (edk2toollib):
|
||||
|
||||
```py
|
||||
from edk2toollib.utility_functions import RunCmd
|
||||
```
|
||||
|
||||
You simply need to install the following pip module to use this library: `edk2-pytool-library`
|
||||
(e.g. `pip install edk2-pytool-library`)
|
||||
|
||||
More information is available here:
|
||||
|
||||
- PyPI page: [edk2-pytool-library](https://pypi.org/project/edk2-pytool-library/)
|
||||
- GitHub repo: [tianocore/edk2-pytool-library](https://github.com/tianocore/edk2-pytool-library)
|
||||
|
||||
If you strongly prefer not including this additional dependency, the functionality imported here is relatively
|
||||
simple to substitute with the Python [`subprocess`](https://docs.python.org/3/library/subprocess.html) built-in
|
||||
module.
|
||||
|
||||
### Examples
|
||||
|
||||
Simple run against current directory:
|
||||
|
||||
`> python DebugMacroCheck.py -w .`
|
||||
|
||||
Simple run against a single file:
|
||||
|
||||
`> python DebugMacroCheck.py -i filename.c`
|
||||
|
||||
Run against a directory with output placed into a file called "debug_macro_check.log":
|
||||
|
||||
`> python DebugMacroCheck.py -w . -l`
|
||||
|
||||
Run against a directory with output placed into a file called "custom.log" and debug log messages enabled:
|
||||
|
||||
`> python DebugMacroCheck.py -w . -l custom.log -v`
|
||||
|
||||
Run against a directory with output placed into a file called "custom.log", with debug log messages enabled including
|
||||
python script function and line number, use a substitution file called "file_sub.yaml", do not show the progress bar,
|
||||
and run against .c and .h files:
|
||||
|
||||
`> python DebugMacroCheck.py -w . -l custom.log -vv -s file_sub.yaml -n -e .c .h`
|
||||
|
||||
> **Note**: It is normally not recommended to run against .h files as they and many other non-.c files normally do
|
||||
not have full `DEBUG` macro prints.
|
||||
|
||||
```plaintext
|
||||
usage: Debug Macro Checker [-h] (-w WORKSPACE_DIRECTORY | -i [INPUT_FILE]) [-l [LOG_FILE]] [-s SUBSTITUTION_FILE] [-v] [-n] [-q] [-u]
|
||||
[-df] [-ds] [-e [EXTENSIONS ...]]
|
||||
|
||||
Checks for debug macro formatting errors within files recursively located within a given directory.
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-w WORKSPACE_DIRECTORY, --workspace-directory WORKSPACE_DIRECTORY
|
||||
Directory of source files to check.
|
||||
|
||||
-i [INPUT_FILE], --input-file [INPUT_FILE]
|
||||
File path for an input file to check.
|
||||
|
||||
Note that some other options do not apply if a single file is specified such as the
|
||||
git options and file extensions.
|
||||
|
||||
-e [EXTENSIONS ...], --extensions [EXTENSIONS ...]
|
||||
List of file extensions to include.
|
||||
(default: ['.c'])
|
||||
|
||||
Optional input and output:
|
||||
-l [LOG_FILE], --log-file [LOG_FILE]
|
||||
File path for log output.
|
||||
(default: if the flag is given with no file path then a file called
|
||||
debug_macro_check.log is created and used in the current directory)
|
||||
|
||||
-s SUBSTITUTION_FILE, --substitution-file SUBSTITUTION_FILE
|
||||
A substitution YAML file specifies string substitutions to perform within the debug macro.
|
||||
|
||||
This is intended to be a simple mechanism to expand the rare cases of pre-processor
|
||||
macros without directly involving the pre-processor. The file consists of one or more
|
||||
string value pairs where the key is the identifier to replace and the value is the value
|
||||
to replace it with.
|
||||
|
||||
This can also be used as a method to ignore results by replacing the problematic string
|
||||
with a different string.
|
||||
|
||||
-v, --verbose-log-file
|
||||
Set file logging verbosity level.
|
||||
- None: Info & > level messages
|
||||
- '-v': + Debug level messages
|
||||
- '-vv': + File name and function
|
||||
- '-vvv': + Line number
|
||||
- '-vvvv': + Timestamp
|
||||
(default: verbose logging is not enabled)
|
||||
|
||||
-n, --no-progress-bar
|
||||
Disables progress bars.
|
||||
(default: progress bars are used in some places to show progress)
|
||||
|
||||
-q, --quiet Disables console output.
|
||||
(default: console output is enabled)
|
||||
|
||||
-u, --utf8w Shows warnings for file UTF-8 decode errors.
|
||||
(default: UTF-8 decode errors are not shown)
|
||||
|
||||
|
||||
Optional git control:
|
||||
-df, --do-not-ignore-git-ignore-files
|
||||
Do not ignore git ignored files.
|
||||
(default: files in git ignore files are ignored)
|
||||
|
||||
-ds, --do-not-ignore-git_submodules
|
||||
Do not ignore files in git submodules.
|
||||
(default: files in git submodules are ignored)
|
||||
```
|
||||
|
||||
## String Substitutions
|
||||
|
||||
`DebugMacroCheck` currently runs separate from the compiler toolchain. This has the advantage that it is very portable
|
||||
and can run early in the build process, but it also means pre-processor macro expansion does not happen when it is
|
||||
invoked.
|
||||
|
||||
In practice, it has been very rare that this is an issue for how most debug macros are written. In case it is, a
|
||||
substitution file can be used to inform `DebugMacroCheck` about the string substitution the pre-processor would
|
||||
perform.
|
||||
|
||||
This pattern should be taken as a warning. It is just as difficult for humans to keep debug macro specifiers and
|
||||
arguments balanced as it is for `DebugMacroCheck` pre-processor macro substitution is used. By separating the string
|
||||
from the actual arguments provided, it is more likely for developers to make mistakes matching print specifiers in
|
||||
the string to the arguments. If usage is reasonable, a string substitution can be used as needed.
|
||||
|
||||
### Ignoring Errors
|
||||
|
||||
Since substitution files perform a straight textual substitution in macros discovered, it can be used to replace
|
||||
problematic text with text that passes allowing errors to be ignored.
|
||||
|
||||
## Python Version Required (3.10)
|
||||
|
||||
This script is written to take advantage of new Python language features in Python 3.10. If you are not using Python
|
||||
3.10 or later, you can:
|
||||
|
||||
1. Upgrade to Python 3.10 or greater
|
||||
2. Run this script in a [virtual environment](https://docs.python.org/3/tutorial/venv.html) with Python 3.10
|
||||
or greater
|
||||
3. Customize the script for compatibility with your Python version
|
||||
|
||||
These are listed in order of recommendation. **(1)** is the simplest option and will upgrade your environment to a
|
||||
newer, safer, and better Python experience. **(2)** is the simplest approach to isolate dependencies to what is needed
|
||||
to run this script without impacting the rest of your system environment. **(3)** creates a one-off fork of the script
|
||||
that, by nature, has a limited lifespan and will make accepting future updates difficult but can be done with relatively
|
||||
minimal effort back to recent Python 3 releases.
|
674
BaseTools/Plugin/DebugMacroCheck/tests/DebugMacroDataSet.py
Normal file
674
BaseTools/Plugin/DebugMacroCheck/tests/DebugMacroDataSet.py
Normal file
@ -0,0 +1,674 @@
|
||||
# @file DebugMacroDataSet.py
|
||||
#
|
||||
# Contains a debug macro test data set for verifying debug macros are
|
||||
# recognized and parsed properly.
|
||||
#
|
||||
# This data is automatically converted into test cases. Just add the new
|
||||
# data object here and run the tests.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
from .MacroTest import (NoSpecifierNoArgumentMacroTest,
|
||||
EqualSpecifierEqualArgumentMacroTest,
|
||||
MoreSpecifiersThanArgumentsMacroTest,
|
||||
LessSpecifiersThanArgumentsMacroTest,
|
||||
IgnoredSpecifiersMacroTest,
|
||||
SpecialParsingMacroTest,
|
||||
CodeSnippetMacroTest)
|
||||
|
||||
|
||||
# Ignore flake8 linter errors for lines that are too long (E501)
|
||||
# flake8: noqa: E501
|
||||
|
||||
# Data Set of DEBUG macros and expected results.
|
||||
# macro: A string representing a DEBUG macro.
|
||||
# result: A tuple with the following value representations.
|
||||
# [0]: Count of total formatting errors
|
||||
# [1]: Count of print specifiers found
|
||||
# [2]: Count of macro arguments found
|
||||
DEBUG_MACROS = [
|
||||
#####################################################################
|
||||
# Section: No Print Specifiers No Arguments
|
||||
#####################################################################
|
||||
NoSpecifierNoArgumentMacroTest(
|
||||
r'',
|
||||
(0, 0, 0)
|
||||
),
|
||||
NoSpecifierNoArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_ERROR, "\\"));',
|
||||
(0, 0, 0)
|
||||
),
|
||||
NoSpecifierNoArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_EVENT, ""));',
|
||||
(0, 0, 0)
|
||||
),
|
||||
NoSpecifierNoArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_EVENT, "\n"));',
|
||||
(0, 0, 0)
|
||||
),
|
||||
NoSpecifierNoArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_EVENT, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"));',
|
||||
(0, 0, 0)
|
||||
),
|
||||
NoSpecifierNoArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_EVENT, "GCD:Initial GCD Memory Space Map\n"));',
|
||||
(0, 0, 0)
|
||||
),
|
||||
NoSpecifierNoArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_GCD, "GCD:Initial GCD Memory Space Map\n"));',
|
||||
(0, 0, 0)
|
||||
),
|
||||
NoSpecifierNoArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_INFO, " Retuning TimerCnt Disabled\n"));',
|
||||
(0, 0, 0)
|
||||
),
|
||||
|
||||
#####################################################################
|
||||
# Section: Equal Print Specifiers to Arguments
|
||||
#####################################################################
|
||||
EqualSpecifierEqualArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_INFO, "%d", Number));',
|
||||
(0, 1, 1)
|
||||
),
|
||||
EqualSpecifierEqualArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReset(MediaId=0x%x)\n", This->Media->MediaId));',
|
||||
(0, 1, 1)
|
||||
),
|
||||
EqualSpecifierEqualArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_INFO, " Retuning TimerCnt %dseconds\n", 2 * (Capability->TimerCount - 1)));',
|
||||
(0, 1, 1)
|
||||
),
|
||||
EqualSpecifierEqualArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_ERROR, "UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status));',
|
||||
(0, 2, 2)
|
||||
),
|
||||
EqualSpecifierEqualArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_ERROR, "UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status));',
|
||||
(0, 2, 2)
|
||||
),
|
||||
EqualSpecifierEqualArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_INFO, "Find GPT Partition [0x%lx", PartitionEntryBuffer[Index].StartingLBA));',
|
||||
(0, 1, 1)
|
||||
),
|
||||
EqualSpecifierEqualArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_ERROR, "Failed to locate gEdkiiBootLogo2ProtocolGuid Status = %r. No Progress bar support. \n", Status));',
|
||||
(0, 1, 1)
|
||||
),
|
||||
EqualSpecifierEqualArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_LOAD, " (%s)", Image->ExitData));',
|
||||
(0, 1, 1)
|
||||
),
|
||||
EqualSpecifierEqualArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_DISPATCH, "%a%r%s%lx%p%c%g", Ascii, Status, Unicode, Hex, Pointer, Character, Guid));',
|
||||
(0, 7, 7)
|
||||
),
|
||||
EqualSpecifierEqualArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - LoadRecoveryCapsule (%d) - %r\n", CapsuleInstance, Status));',
|
||||
(0, 2, 2)
|
||||
),
|
||||
EqualSpecifierEqualArgumentMacroTest(
|
||||
r'DEBUG ((DEBUG_DISPATCH, "%a%r%s%lx%p%c%g%a%r%s%lx%p%c%g%a%r%s%lx%p%c%g%a%r%s%lx%p%c%g", Ascii, Status, Unicode, Hex, Pointer, Character, Guid, Ascii, Status, Unicode, Hex, Pointer, Character, Guid, Ascii, Status, Unicode, Hex, Pointer, Character, Guid, Ascii, Status, Unicode, Hex, Pointer, Character, Guid));',
|
||||
(0, 28, 28)
|
||||
),
|
||||
|
||||
#####################################################################
|
||||
# Section: More Print Specifiers Than Arguments
|
||||
#####################################################################
|
||||
MoreSpecifiersThanArgumentsMacroTest(
|
||||
r'DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReadBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));',
|
||||
(1, 5, 4)
|
||||
),
|
||||
MoreSpecifiersThanArgumentsMacroTest(
|
||||
r'DEBUG ((DEBUG_INFO, "%a: Request=%s\n", __func__));',
|
||||
(1, 2, 1)
|
||||
),
|
||||
MoreSpecifiersThanArgumentsMacroTest(
|
||||
r'DEBUG ((DEBUG_ERROR, "%a: Invalid request format %d for %d\n", CertFormat, CertRequest));',
|
||||
(1, 3, 2)
|
||||
),
|
||||
|
||||
#####################################################################
|
||||
# Section: Less Print Specifiers Than Arguments
|
||||
#####################################################################
|
||||
LessSpecifiersThanArgumentsMacroTest(
|
||||
r'DEBUG ((DEBUG_INFO, "Find GPT Partition [0x%lx", PartitionEntryBuffer[Index].StartingLBA, BlockDevPtr->LastBlock));',
|
||||
(1, 1, 2)
|
||||
),
|
||||
LessSpecifiersThanArgumentsMacroTest(
|
||||
r'DEBUG ((DEBUG_INFO, " Retuning TimerCnt Disabled\n", 2 * (Capability->TimerCount - 1)));',
|
||||
(1, 0, 1)
|
||||
),
|
||||
LessSpecifiersThanArgumentsMacroTest(
|
||||
r'DEBUG ((DEBUG_ERROR, "Failed to locate gEdkiiBootLogo2ProtocolGuid. No Progress bar support. \n", Status));',
|
||||
(1, 0, 1)
|
||||
),
|
||||
LessSpecifiersThanArgumentsMacroTest(
|
||||
r'DEBUG ((DEBUG_ERROR, "UsbEnumeratePort: Critical Over Current\n", Port));',
|
||||
(1, 0, 1)
|
||||
),
|
||||
LessSpecifiersThanArgumentsMacroTest(
|
||||
r'DEBUG ((DEBUG_ERROR, "[TPM2] Submit PP Request failure! Sync PPRQ/PPRM with PP variable.\n", Status));',
|
||||
(1, 0, 1)
|
||||
),
|
||||
LessSpecifiersThanArgumentsMacroTest(
|
||||
r'DEBUG ((DEBUG_ERROR, ": Failed to update debug log index file: %r !\n", __func__, Status));',
|
||||
(1, 1, 2)
|
||||
),
|
||||
LessSpecifiersThanArgumentsMacroTest(
|
||||
r'DEBUG ((DEBUG_ERROR, "%a - Failed to extract nonce from policy blob with return status %r\n", __func__, gPolicyBlobFieldName[MFCI_POLICY_TARGET_NONCE], Status));',
|
||||
(1, 2, 3)
|
||||
),
|
||||
|
||||
#####################################################################
|
||||
# Section: Macros with Ignored Specifiers
|
||||
#####################################################################
|
||||
IgnoredSpecifiersMacroTest(
|
||||
r'DEBUG ((DEBUG_INIT, "%HEmuOpenBlock: opened %a%N\n", Private->Filename));',
|
||||
(0, 1, 1)
|
||||
),
|
||||
IgnoredSpecifiersMacroTest(
|
||||
r'DEBUG ((DEBUG_LOAD, " (%hs)", Image->ExitData));',
|
||||
(0, 1, 1)
|
||||
),
|
||||
IgnoredSpecifiersMacroTest(
|
||||
r'DEBUG ((DEBUG_LOAD, "%H%s%N: Unknown flag - ''%H%s%N''\r\n", String1, String2));',
|
||||
(0, 2, 2)
|
||||
),
|
||||
|
||||
#####################################################################
|
||||
# Section: Macros with Special Parsing Scenarios
|
||||
#####################################################################
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_INFO, " File Name: %a\n", "Document.txt"))',
|
||||
(0, 1, 1),
|
||||
"Malformatted Macro - Missing Semicolon"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG (DEBUG_INFO, " File Name: %a\n", "Document.txt");',
|
||||
(0, 0, 0),
|
||||
"Malformatted Macro - Missing Two Parentheses"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_INFO, "%a\n", "Removable Slot"));',
|
||||
(0, 1, 1),
|
||||
"Single String Argument in Quotes"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_INFO, " SDR50 Tuning %a\n", Capability->TuningSDR50 ? "TRUE" : "FALSE"));',
|
||||
(0, 1, 1),
|
||||
"Ternary Operator Present"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_INFO, " SDR50 Tuning %a\n", Capability->TuningSDR50 ? "TRUE" : "FALSE"));',
|
||||
(0, 1, 1),
|
||||
"Ternary Operator Present"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((DEBUG_ERROR, "\\"));
|
||||
DEBUG ((DEBUG_ERROR, "\\"));
|
||||
DEBUG ((DEBUG_ERROR, "\\"));
|
||||
DEBUG ((DEBUG_ERROR, "\\"));
|
||||
''',
|
||||
(0, 0, 0),
|
||||
"Multiple Macros with an Escaped Character"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"UsbEnumerateNewDev: device uses translator (%d, %d)\n",
|
||||
Child->Translator.TranslatorHubAddress,
|
||||
Child->Translator.TranslatorPortNumber
|
||||
));
|
||||
''',
|
||||
(0, 2, 2),
|
||||
"Multi-line Macro"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"UsbEnumeratePort: port %d state - %02x, change - %02x on %p\n",
|
||||
Port,
|
||||
PortState.PortStatus,
|
||||
PortState.PortChangeStatus,
|
||||
HubIf
|
||||
));
|
||||
''',
|
||||
(0, 4, 4),
|
||||
"Multi-line Macro"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"%a:%a: failed to allocate reserved pages: "
|
||||
"BufferSize=%Lu LoadFile=\"%s\" FilePath=\"%s\"\n",
|
||||
gEfiCallerBaseName,
|
||||
__func__,
|
||||
(UINT64)BufferSize,
|
||||
LoadFileText,
|
||||
FileText
|
||||
));
|
||||
''',
|
||||
(0, 5, 5),
|
||||
"Multi-line Macro with Compiler String Concatenation"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"ERROR: GTDT: GT Block Frame Info Structures %d and %d have the same " \
|
||||
"frame number: 0x%x.\n",
|
||||
Index1,
|
||||
Index2,
|
||||
FrameNumber1
|
||||
));
|
||||
''',
|
||||
(0, 3, 3),
|
||||
"Multi-line Macro with Backslash String Concatenation"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"ERROR: PPTT: Too many private resources. Count = %d. " \
|
||||
"Maximum supported Processor Node size exceeded. " \
|
||||
"Token = %p. Status = %r\n",
|
||||
ProcInfoNode->NoOfPrivateResources,
|
||||
ProcInfoNode->ParentToken,
|
||||
Status
|
||||
));
|
||||
''',
|
||||
(0, 3, 3),
|
||||
"Multi-line Macro with Backslash String Concatenation"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_VERBOSE,
|
||||
"% 20a % 20a % 20a % 20a\n",
|
||||
"PhysicalStart(0x)",
|
||||
"PhysicalSize(0x)",
|
||||
"CpuStart(0x)",
|
||||
"RegionState(0x)"
|
||||
));
|
||||
''',
|
||||
(0, 4, 4),
|
||||
"Multi-line Macro with Quoted String Arguments"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"XenPvBlk: "
|
||||
"%a error %d on %a at sector %Lx, num bytes %Lx\n",
|
||||
Response->operation == BLKIF_OP_READ ? "read" : "write",
|
||||
Status,
|
||||
IoData->Dev->NodeName,
|
||||
(UINT64)IoData->Sector,
|
||||
(UINT64)IoData->Size
|
||||
));
|
||||
''',
|
||||
(0, 5, 5),
|
||||
"Multi-line Macro with Ternary Operator and Quoted String Arguments"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"%a: Label=\"%s\" OldParentNodeId=%Lu OldName=\"%a\" "
|
||||
"NewParentNodeId=%Lu NewName=\"%a\" Errno=%d\n",
|
||||
__func__,
|
||||
VirtioFs->Label,
|
||||
OldParentNodeId,
|
||||
OldName,
|
||||
NewParentNodeId,
|
||||
NewName,
|
||||
CommonResp.Error
|
||||
));
|
||||
''',
|
||||
(0, 7, 7),
|
||||
"Multi-line Macro with Escaped Quotes and String Concatenation"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((DEBUG_WARN, "Failed to retrieve Variable:\"MebxData\", Status = %r\n", Status));
|
||||
''',
|
||||
(0, 1, 1),
|
||||
"Escaped Parentheses in Debug Message"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG((DEBUG_INFO, "%0d %s", XbB_ddr4[1][bankBit][xorBit], xorBit == (XaB_NUM_OF_BITS-1) ? "]": ", "));
|
||||
''',
|
||||
(0, 2, 2),
|
||||
"Parentheses in Ternary Operator Expression"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_INFO | DEBUG_EVENT | DEBUG_WARN, " %u\n", &Structure->Block.Value));',
|
||||
(0, 1, 1),
|
||||
"Multiple Print Specifier Levels Present"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, " %s\n", ReturnString()));',
|
||||
(0, 1, 1),
|
||||
"Function Call Argument No Params"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, " %s\n", ReturnString(&Param1)));',
|
||||
(0, 1, 1),
|
||||
"Function Call Argument 1 Param"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, " %s\n", ReturnString(&Param1, Param2)));',
|
||||
(0, 1, 1),
|
||||
"Function Call Argument Multiple Params"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, " %s\n", ReturnString(&Param1, ReturnParam())));',
|
||||
(0, 1, 1),
|
||||
"Function Call Argument 2-Level Depth No 2nd-Level Param"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, " %s\n", ReturnString(&Param1, ReturnParam(*Param))));',
|
||||
(0, 1, 1),
|
||||
"Function Call Argument 2-Level Depth 1 2nd-Level Param"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, " %s\n", ReturnString(&Param1, ReturnParam(*Param, &ParamNext))));',
|
||||
(0, 1, 1),
|
||||
"Function Call Argument 2-Level Depth Multiple 2nd-Level Param"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, " %s\n", ReturnString(&Param1, ReturnParam(*Param, GetParam(1, 2, 3)))));',
|
||||
(0, 1, 1),
|
||||
"Function Call Argument 3-Level Depth Multiple Params"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, " %s\n", ReturnString(&Param1, ReturnParam(*Param, GetParam(1, 2, 3), NextParam))));',
|
||||
(0, 1, 1),
|
||||
"Function Call Argument 3-Level Depth Multiple Params with Param After Function Call"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, " %s-%a\n", ReturnString(&Param1), ReturnString2(&ParamN)));',
|
||||
(0, 2, 2),
|
||||
"Multiple Function Call Arguments"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, " %s\n", ReturnString(&Param1), ReturnString2(&ParamN)));',
|
||||
(1, 1, 2),
|
||||
"Multiple Function Call Arguments with Imbalance"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, " %s%s\n", (ReturnString(&Param1)), (ReturnString2(&ParamN))));',
|
||||
(0, 2, 2),
|
||||
"Multiple Function Call Arguments Surrounded with Parentheses"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, " %s\n", ((((ReturnString(&Param1)))))));',
|
||||
(0, 1, 1),
|
||||
"Multiple Function Call Arguments Surrounded with Many Parentheses"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, ""%B%08X%N: %-48a %V*%a*%N"", HexNumber, ReturnString(Array[Index]), &AsciiString[0]));',
|
||||
(0, 3, 3),
|
||||
"Complex String Print Specifier 1"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, "0x%-8x:%H%s%N % -64s(%73-.73s){%g}<%H% -70s%N>\n. Size: 0x%-16x (%-,d) bytes.\n\n", HexNumber, GetUnicodeString (), &UnicodeString[4], UnicodeString2, &Guid, AnotherUnicodeString, Struct.SomeSize, CommaDecimalValue));',
|
||||
(0, 8, 8),
|
||||
"Multiple Complex Print Specifiers 1"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'DEBUG ((DEBUG_WARN, "0x%-8x:%H%s%N % -64s(%73-.73s){%g}<%H% -70s%N%r>\n. Size: 0x%-16x (%-,d) bytes.\n\n", HexNumber, GetUnicodeString (), &UnicodeString[4], UnicodeString2, &Guid, AnotherUnicodeString, Struct.SomeSize, CommaDecimalValue));',
|
||||
(1, 9, 8),
|
||||
"Multiple Complex Print Specifiers Imbalance 1"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
("%a: Label=\"%s\" CanonicalPathname=\"%a\" FileName=\"%s\" "
|
||||
"OpenMode=0x%Lx Attributes=0x%Lx: nonsensical request to possibly "
|
||||
"create a file marked read-only, for read-write access\n"),
|
||||
__func__,
|
||||
VirtioFs->Label,
|
||||
VirtioFsFile->CanonicalPathname,
|
||||
FileName,
|
||||
OpenMode,
|
||||
Attributes
|
||||
));
|
||||
''',
|
||||
(0, 6, 6),
|
||||
"Multi-Line with Parentheses Around Debug String Compiler String Concat"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG (
|
||||
(DEBUG_INFO,
|
||||
" %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",
|
||||
(UINTN)Index,
|
||||
(UINTN)LocalBbsTable[Index].BootPriority,
|
||||
(UINTN)LocalBbsTable[Index].Bus,
|
||||
(UINTN)LocalBbsTable[Index].Device,
|
||||
(UINTN)LocalBbsTable[Index].Function,
|
||||
(UINTN)LocalBbsTable[Index].Class,
|
||||
(UINTN)LocalBbsTable[Index].SubClass,
|
||||
(UINTN)LocalBbsTable[Index].DeviceType,
|
||||
(UINTN)*(UINT16 *)&LocalBbsTable[Index].StatusFlags,
|
||||
(UINTN)LocalBbsTable[Index].BootHandlerSegment,
|
||||
(UINTN)LocalBbsTable[Index].BootHandlerOffset,
|
||||
(UINTN)((LocalBbsTable[Index].MfgStringSegment << 4) + LocalBbsTable[Index].MfgStringOffset),
|
||||
(UINTN)((LocalBbsTable[Index].DescStringSegment << 4) + LocalBbsTable[Index].DescStringOffset))
|
||||
);
|
||||
''',
|
||||
(1, 11, 13),
|
||||
"Multi-line Macro with Many Arguments And Multi-Line Parentheses"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_WARN,
|
||||
"0x%-8x:%H%s%N % -64s(%73-.73s){%g}<%H% -70s%N>\n. Size: 0x%-16x (%-,d) bytes.\n\n",
|
||||
HexNumber,
|
||||
GetUnicodeString (InnerFunctionCall(Arg1, &Arg2)),
|
||||
&UnicodeString[4],
|
||||
UnicodeString2,
|
||||
&Guid,
|
||||
AnotherUnicodeString,
|
||||
Struct.SomeSize,
|
||||
CommaDecimalValue
|
||||
));
|
||||
''',
|
||||
(0, 8, 8),
|
||||
"Multi-line Macro with Multiple Complex Print Specifiers 1 and 2-Depth Function Calls"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG (
|
||||
(DEBUG_NET,
|
||||
"TcpFastRecover: enter fast retransmission for TCB %p, recover point is %d\n",
|
||||
Tcb,
|
||||
Tcb->Recover)
|
||||
);
|
||||
''',
|
||||
(0, 2, 2),
|
||||
"Multi-line Macro with Parentheses Separated"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_VERBOSE,
|
||||
"%a: APIC ID " FMT_APIC_ID " was hot-plugged "
|
||||
"before; ignoring it\n",
|
||||
__func__,
|
||||
NewApicId
|
||||
));
|
||||
''',
|
||||
(1, 1, 2),
|
||||
"Multi-line Imbalanced Macro with Indented String Concatenation"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_VERBOSE,
|
||||
"%a: APIC ID was hot-plugged - %a",
|
||||
__func__,
|
||||
"String with , inside"
|
||||
));
|
||||
''',
|
||||
(0, 2, 2),
|
||||
"Multi-line with Quoted String Argument Containing Comma"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_VERBOSE,
|
||||
"%a: APIC ID was hot-plugged - %a",
|
||||
__func__,
|
||||
"St,ring, with , ins,ide"
|
||||
));
|
||||
''',
|
||||
(0, 2, 2),
|
||||
"Multi-line with Quoted String Argument Containing Multiple Commas"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((DEBUG_VERBOSE, "%a: APIC ID was hot-plugged, \"%a\"", __func__, "S\"t,\"ring, with , ins,i\"de"));
|
||||
''',
|
||||
(0, 2, 2),
|
||||
"Quoted String Argument with Escaped Quotes and Multiple Commas"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"%a: AddProcessor(" FMT_APIC_ID "): %r\n",
|
||||
__func__,
|
||||
Status
|
||||
));
|
||||
''',
|
||||
(0, 2, 2),
|
||||
"Quoted Parenthesized String Inside Debug Message String"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"%a: hot-added APIC ID " FMT_APIC_ID ", SMBASE 0x%Lx, "
|
||||
"EFI_SMM_CPU_SERVICE_PROTOCOL assigned number %Lu\n",
|
||||
__func__,
|
||||
(UINT64)mCpuHotPlugData->SmBase[NewSlot],
|
||||
(UINT64)NewProcessorNumberByProtocol
|
||||
));
|
||||
''',
|
||||
(0, 3, 3),
|
||||
"Quoted String with Concatenation Inside Debug Message String"
|
||||
),
|
||||
SpecialParsingMacroTest(
|
||||
r'''
|
||||
DEBUG ((DEBUG_INFO, Index == COLUMN_SIZE/2 ? "0" : " %02x", (UINTN)Data[Index]));
|
||||
''',
|
||||
(0, 1, 1),
|
||||
"Ternary Operating in Debug Message String"
|
||||
),
|
||||
|
||||
#####################################################################
|
||||
# Section: Code Snippet Tests
|
||||
#####################################################################
|
||||
CodeSnippetMacroTest(
|
||||
r'''
|
||||
/**
|
||||
Print the BBS Table.
|
||||
|
||||
@param LocalBbsTable The BBS table.
|
||||
@param BbsCount The count of entry in BBS table.
|
||||
**/
|
||||
VOID
|
||||
LegacyBmPrintBbsTable (
|
||||
IN BBS_TABLE *LocalBbsTable,
|
||||
IN UINT16 BbsCount
|
||||
)
|
||||
{
|
||||
UINT16 Index;
|
||||
|
||||
DEBUG ((DEBUG_INFO, "\n"));
|
||||
DEBUG ((DEBUG_INFO, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
|
||||
DEBUG ((DEBUG_INFO, "=============================================\n"));
|
||||
for (Index = 0; Index < BbsCount; Index++) {
|
||||
if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG (
|
||||
(DEBUG_INFO,
|
||||
" %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n",
|
||||
(UINTN)Index,
|
||||
(UINTN)LocalBbsTable[Index].BootPriority,
|
||||
(UINTN)LocalBbsTable[Index].Bus,
|
||||
(UINTN)LocalBbsTable[Index].Device,
|
||||
(UINTN)LocalBbsTable[Index].Function,
|
||||
(UINTN)LocalBbsTable[Index].Class,
|
||||
(UINTN)LocalBbsTable[Index].SubClass,
|
||||
(UINTN)LocalBbsTable[Index].DeviceType,
|
||||
(UINTN)*(UINT16 *)&LocalBbsTable[Index].StatusFlags,
|
||||
(UINTN)LocalBbsTable[Index].BootHandlerSegment,
|
||||
(UINTN)LocalBbsTable[Index].BootHandlerOffset,
|
||||
(UINTN)((LocalBbsTable[Index].MfgStringSegment << 4) + LocalBbsTable[Index].MfgStringOffset),
|
||||
(UINTN)((LocalBbsTable[Index].DescStringSegment << 4) + LocalBbsTable[Index].DescStringOffset))
|
||||
);
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, "\n"));
|
||||
''',
|
||||
(1, 0, 0),
|
||||
"Code Section with An Imbalanced Macro"
|
||||
),
|
||||
CodeSnippetMacroTest(
|
||||
r'''
|
||||
if (*Buffer == AML_ROOT_CHAR) {
|
||||
//
|
||||
// RootChar
|
||||
//
|
||||
Buffer++;
|
||||
DEBUG ((DEBUG_ERROR, "\\"));
|
||||
} else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
|
||||
//
|
||||
// ParentPrefixChar
|
||||
//
|
||||
do {
|
||||
Buffer++;
|
||||
DEBUG ((DEBUG_ERROR, "^"));
|
||||
} while (*Buffer == AML_PARENT_PREFIX_CHAR);
|
||||
}
|
||||
DEBUG ((DEBUG_WARN, "Failed to retrieve Variable:\"MebxData\", Status = %r\n", Status));
|
||||
''',
|
||||
(0, 1, 1),
|
||||
"Code Section with Escaped Backslash and Escaped Quotes"
|
||||
),
|
||||
CodeSnippetMacroTest(
|
||||
r'''
|
||||
if (EFI_ERROR (Status)) {
|
||||
UINTN Offset;
|
||||
UINTN Start;
|
||||
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"Variable FV header is not valid. It will be reinitialized.\n"
|
||||
));
|
||||
|
||||
//
|
||||
// Get FvbInfo to provide in FwhInstance.
|
||||
//
|
||||
Status = GetFvbInfo (Length, &GoodFwVolHeader);
|
||||
ASSERT (!EFI_ERROR (Status));
|
||||
}
|
||||
''',
|
||||
(0, 0, 0),
|
||||
"Code Section with Multi-Line Macro with No Arguments"
|
||||
)
|
||||
]
|
131
BaseTools/Plugin/DebugMacroCheck/tests/MacroTest.py
Normal file
131
BaseTools/Plugin/DebugMacroCheck/tests/MacroTest.py
Normal file
@ -0,0 +1,131 @@
|
||||
# @file MacroTest.py
|
||||
#
|
||||
# Contains the data classes that are used to compose debug macro tests.
|
||||
#
|
||||
# All data classes inherit from a single abstract base class that expects
|
||||
# the subclass to define the category of test it represents.
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from os import linesep
|
||||
from typing import Tuple
|
||||
|
||||
import abc
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class MacroTest(abc.ABC):
|
||||
"""Abstract base class for an individual macro test case."""
|
||||
|
||||
macro: str
|
||||
result: Tuple[int, int, int]
|
||||
description: str = field(default='')
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def category(self) -> str:
|
||||
"""Returns the test class category identifier.
|
||||
|
||||
Example: 'equal_specifier_equal_argument_macro_test'
|
||||
|
||||
This string is used to bind test objects against this class.
|
||||
|
||||
Returns:
|
||||
str: Test category identifier string.
|
||||
"""
|
||||
pass
|
||||
|
||||
@property
|
||||
def category_description(self) -> str:
|
||||
"""Returns the test class category description.
|
||||
|
||||
Example: 'Test case with equal count of print specifiers to arguments.'
|
||||
|
||||
This string is a human readable description of the test category.
|
||||
|
||||
Returns:
|
||||
str: String describing the test category.
|
||||
"""
|
||||
return self.__doc__
|
||||
|
||||
def __str__(self):
|
||||
"""Returns a macro test case description string."""
|
||||
|
||||
s = [
|
||||
f"{linesep}",
|
||||
"=" * 80,
|
||||
f"Macro Test Type: {self.category_description}",
|
||||
f"{linesep}Macro: {self.macro}",
|
||||
f"{linesep}Expected Result: {self.result}"
|
||||
]
|
||||
|
||||
if self.description:
|
||||
s.insert(3, f"Test Description: {self.description}")
|
||||
|
||||
return f'{linesep}'.join(s)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class NoSpecifierNoArgumentMacroTest(MacroTest):
|
||||
"""Test case with no print specifier and no arguments."""
|
||||
|
||||
@property
|
||||
def category(self) -> str:
|
||||
return "no_specifier_no_argument_macro_test"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class EqualSpecifierEqualArgumentMacroTest(MacroTest):
|
||||
"""Test case with equal count of print specifiers to arguments."""
|
||||
|
||||
@property
|
||||
def category(self) -> str:
|
||||
return "equal_specifier_equal_argument_macro_test"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class MoreSpecifiersThanArgumentsMacroTest(MacroTest):
|
||||
"""Test case with more print specifiers than arguments."""
|
||||
|
||||
@property
|
||||
def category(self) -> str:
|
||||
return "more_specifiers_than_arguments_macro_test"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class LessSpecifiersThanArgumentsMacroTest(MacroTest):
|
||||
"""Test case with less print specifiers than arguments."""
|
||||
|
||||
@property
|
||||
def category(self) -> str:
|
||||
return "less_specifiers_than_arguments_macro_test"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class IgnoredSpecifiersMacroTest(MacroTest):
|
||||
"""Test case to test ignored print specifiers."""
|
||||
|
||||
@property
|
||||
def category(self) -> str:
|
||||
return "ignored_specifiers_macro_test"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SpecialParsingMacroTest(MacroTest):
|
||||
"""Test case with special (complicated) parsing scenarios."""
|
||||
|
||||
@property
|
||||
def category(self) -> str:
|
||||
return "special_parsing_macro_test"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class CodeSnippetMacroTest(MacroTest):
|
||||
"""Test case within a larger code snippet."""
|
||||
|
||||
@property
|
||||
def category(self) -> str:
|
||||
return "code_snippet_macro_test"
|
0
BaseTools/Plugin/DebugMacroCheck/tests/__init__.py
Normal file
0
BaseTools/Plugin/DebugMacroCheck/tests/__init__.py
Normal file
201
BaseTools/Plugin/DebugMacroCheck/tests/test_DebugMacroCheck.py
Normal file
201
BaseTools/Plugin/DebugMacroCheck/tests/test_DebugMacroCheck.py
Normal file
@ -0,0 +1,201 @@
|
||||
# @file test_DebugMacroCheck.py
|
||||
#
|
||||
# Contains unit tests for the DebugMacroCheck build plugin.
|
||||
#
|
||||
# An example of running these tests from the root of the workspace:
|
||||
# python -m unittest discover -s ./BaseTools/Plugin/DebugMacroCheck/tests -v
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
import inspect
|
||||
import pathlib
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
# Import the build plugin
|
||||
test_file = pathlib.Path(__file__)
|
||||
sys.path.append(str(test_file.parent.parent))
|
||||
|
||||
# flake8 (E402): Ignore flake8 module level import not at top of file
|
||||
import DebugMacroCheck # noqa: E402
|
||||
|
||||
from os import linesep # noqa: E402
|
||||
from tests import DebugMacroDataSet # noqa: E402
|
||||
from tests import MacroTest # noqa: E402
|
||||
from typing import Callable, Tuple # noqa: E402
|
||||
|
||||
|
||||
#
|
||||
# This metaclass is provided to dynamically produce test case container
|
||||
# classes. The main purpose of this approach is to:
|
||||
# 1. Allow categories of test cases to be defined (test container classes)
|
||||
# 2. Allow test cases to automatically (dynamically) be assigned to their
|
||||
# corresponding test container class when new test data is defined.
|
||||
#
|
||||
# The idea being that infrastructure and test data are separated. Adding
|
||||
# / removing / modifying test data does not require an infrastructure
|
||||
# change (unless new categories are defined).
|
||||
# 3. To work with the unittest discovery algorithm and VS Code Test Explorer.
|
||||
#
|
||||
# Notes:
|
||||
# - (1) can roughly be achieved with unittest test suites. In another
|
||||
# implementation approach, this solution was tested with relatively minor
|
||||
# modifications to use test suites. However, this became a bit overly
|
||||
# complicated with the dynamic test case method generation and did not
|
||||
# work as well with VS Code Test Explorer.
|
||||
# - For (2) and (3), particularly for VS Code Test Explorer to work, the
|
||||
# dynamic population of the container class namespace needed to happen prior
|
||||
# to class object creation. That is why the metaclass assigns test methods
|
||||
# to the new classes based upon the test category specified in the
|
||||
# corresponding data class.
|
||||
# - This could have been simplified a bit by either using one test case
|
||||
# container class and/or testing data in a single, monolithic test function
|
||||
# that iterates over the data set. However, the dynamic hierarchy greatly
|
||||
# helps organize test results and reporting. The infrastructure though
|
||||
# inheriting some complexity to support it, should not need to change (much)
|
||||
# as the data set expands.
|
||||
# - Test case categories (container classes) are derived from the overall
|
||||
# type of macro conditions under test.
|
||||
#
|
||||
# - This implementation assumes unittest will discover test cases
|
||||
# (classes derived from unittest.TestCase) with the name pattern "Test_*"
|
||||
# and test functions with the name pattern "test_x". Individual tests are
|
||||
# dynamically numbered monotonically within a category.
|
||||
# - The final test case description is also able to return fairly clean
|
||||
# context information.
|
||||
#
|
||||
class Meta_TestDebugMacroCheck(type):
|
||||
"""
|
||||
Metaclass for debug macro test case class factory.
|
||||
"""
|
||||
@classmethod
|
||||
def __prepare__(mcls, name, bases, **kwargs):
|
||||
"""Returns the test case namespace for this class."""
|
||||
candidate_macros, cls_ns, cnt = [], {}, 0
|
||||
|
||||
if "category" in kwargs.keys():
|
||||
candidate_macros = [m for m in DebugMacroDataSet.DEBUG_MACROS if
|
||||
m.category == kwargs["category"]]
|
||||
else:
|
||||
candidate_macros = DebugMacroDataSet.DEBUG_MACROS
|
||||
|
||||
for cnt, macro_test in enumerate(candidate_macros):
|
||||
f_name = f'test_{macro_test.category}_{cnt}'
|
||||
t_desc = f'{macro_test!s}'
|
||||
cls_ns[f_name] = mcls.build_macro_test(macro_test, t_desc)
|
||||
return cls_ns
|
||||
|
||||
def __new__(mcls, name, bases, ns, **kwargs):
|
||||
"""Defined to prevent variable args from bubbling to the base class."""
|
||||
return super().__new__(mcls, name, bases, ns)
|
||||
|
||||
def __init__(mcls, name, bases, ns, **kwargs):
|
||||
"""Defined to prevent variable args from bubbling to the base class."""
|
||||
return super().__init__(name, bases, ns)
|
||||
|
||||
@classmethod
|
||||
def build_macro_test(cls, macro_test: MacroTest.MacroTest,
|
||||
test_desc: str) -> Callable[[None], None]:
|
||||
"""Returns a test function for this macro test data."
|
||||
|
||||
Args:
|
||||
macro_test (MacroTest.MacroTest): The macro test class.
|
||||
|
||||
test_desc (str): A test description string.
|
||||
|
||||
Returns:
|
||||
Callable[[None], None]: A test case function.
|
||||
"""
|
||||
def test_func(self):
|
||||
act_result = cls.check_regex(macro_test.macro)
|
||||
self.assertCountEqual(
|
||||
act_result,
|
||||
macro_test.result,
|
||||
test_desc + f'{linesep}'.join(
|
||||
["", f"Actual Result: {act_result}", "=" * 80, ""]))
|
||||
|
||||
return test_func
|
||||
|
||||
@classmethod
|
||||
def check_regex(cls, source_str: str) -> Tuple[int, int, int]:
|
||||
"""Returns the plugin result for the given macro string.
|
||||
|
||||
Args:
|
||||
source_str (str): A string containing debug macros.
|
||||
|
||||
Returns:
|
||||
Tuple[int, int, int]: A tuple of the number of formatting errors,
|
||||
number of print specifiers, and number of arguments for the macros
|
||||
given.
|
||||
"""
|
||||
return DebugMacroCheck.check_debug_macros(
|
||||
DebugMacroCheck.get_debug_macros(source_str),
|
||||
cls._get_function_name())
|
||||
|
||||
@classmethod
|
||||
def _get_function_name(cls) -> str:
|
||||
"""Returns the function name from one level of call depth.
|
||||
|
||||
Returns:
|
||||
str: The caller function name.
|
||||
"""
|
||||
return "function: " + inspect.currentframe().f_back.f_code.co_name
|
||||
|
||||
|
||||
# Test container classes for dynamically generated macro test cases.
|
||||
# A class can be removed below to skip / remove it from testing.
|
||||
# Test case functions will be added to the appropriate class as they are
|
||||
# created.
|
||||
class Test_NoSpecifierNoArgument(
|
||||
unittest.TestCase,
|
||||
metaclass=Meta_TestDebugMacroCheck,
|
||||
category="no_specifier_no_argument_macro_test"):
|
||||
pass
|
||||
|
||||
|
||||
class Test_EqualSpecifierEqualArgument(
|
||||
unittest.TestCase,
|
||||
metaclass=Meta_TestDebugMacroCheck,
|
||||
category="equal_specifier_equal_argument_macro_test"):
|
||||
pass
|
||||
|
||||
|
||||
class Test_MoreSpecifiersThanArguments(
|
||||
unittest.TestCase,
|
||||
metaclass=Meta_TestDebugMacroCheck,
|
||||
category="more_specifiers_than_arguments_macro_test"):
|
||||
pass
|
||||
|
||||
|
||||
class Test_LessSpecifiersThanArguments(
|
||||
unittest.TestCase,
|
||||
metaclass=Meta_TestDebugMacroCheck,
|
||||
category="less_specifiers_than_arguments_macro_test"):
|
||||
pass
|
||||
|
||||
|
||||
class Test_IgnoredSpecifiers(
|
||||
unittest.TestCase,
|
||||
metaclass=Meta_TestDebugMacroCheck,
|
||||
category="ignored_specifiers_macro_test"):
|
||||
pass
|
||||
|
||||
|
||||
class Test_SpecialParsingMacroTest(
|
||||
unittest.TestCase,
|
||||
metaclass=Meta_TestDebugMacroCheck,
|
||||
category="special_parsing_macro_test"):
|
||||
pass
|
||||
|
||||
|
||||
class Test_CodeSnippetMacroTest(
|
||||
unittest.TestCase,
|
||||
metaclass=Meta_TestDebugMacroCheck,
|
||||
category="code_snippet_macro_test"):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -76,6 +76,7 @@ def get_section_maintainers(path, section):
|
||||
"""Returns a list with email addresses to any M: and R: entries
|
||||
matching the provided path in the provided section."""
|
||||
maintainers = []
|
||||
reviewers = []
|
||||
lists = []
|
||||
nowarn_status = ['Supported', 'Maintained']
|
||||
|
||||
@ -83,12 +84,18 @@ def get_section_maintainers(path, section):
|
||||
for status in section['status']:
|
||||
if status not in nowarn_status:
|
||||
print('WARNING: Maintained status for "%s" is \'%s\'!' % (path, status))
|
||||
for address in section['maintainer'], section['reviewer']:
|
||||
for address in section['maintainer']:
|
||||
# Convert to list if necessary
|
||||
if isinstance(address, list):
|
||||
maintainers += address
|
||||
else:
|
||||
lists += [address]
|
||||
maintainers += [address]
|
||||
for address in section['reviewer']:
|
||||
# Convert to list if necessary
|
||||
if isinstance(address, list):
|
||||
reviewers += address
|
||||
else:
|
||||
reviewers += [address]
|
||||
for address in section['list']:
|
||||
# Convert to list if necessary
|
||||
if isinstance(address, list):
|
||||
@ -96,32 +103,35 @@ def get_section_maintainers(path, section):
|
||||
else:
|
||||
lists += [address]
|
||||
|
||||
return maintainers, lists
|
||||
return {'maintainers': maintainers, 'reviewers': reviewers, 'lists': lists}
|
||||
|
||||
def get_maintainers(path, sections, level=0):
|
||||
"""For 'path', iterates over all sections, returning maintainers
|
||||
for matching ones."""
|
||||
maintainers = []
|
||||
reviewers = []
|
||||
lists = []
|
||||
for section in sections:
|
||||
tmp_maint, tmp_lists = get_section_maintainers(path, section)
|
||||
if tmp_maint:
|
||||
maintainers += tmp_maint
|
||||
if tmp_lists:
|
||||
lists += tmp_lists
|
||||
recipients = get_section_maintainers(path, section)
|
||||
maintainers += recipients['maintainers']
|
||||
reviewers += recipients['reviewers']
|
||||
lists += recipients['lists']
|
||||
|
||||
if not maintainers:
|
||||
# If no match found, look for match for (nonexistent) file
|
||||
# REPO.working_dir/<default>
|
||||
print('"%s": no maintainers found, looking for default' % path)
|
||||
if level == 0:
|
||||
maintainers = get_maintainers('<default>', sections, level=level + 1)
|
||||
recipients = get_maintainers('<default>', sections, level=level + 1)
|
||||
maintainers += recipients['maintainers']
|
||||
reviewers += recipients['reviewers']
|
||||
lists += recipients['lists']
|
||||
else:
|
||||
print("No <default> maintainers set for project.")
|
||||
if not maintainers:
|
||||
return None
|
||||
|
||||
return maintainers + lists
|
||||
return {'maintainers': maintainers, 'reviewers': reviewers, 'lists': lists}
|
||||
|
||||
def parse_maintainers_line(line):
|
||||
"""Parse one line of Maintainers.txt, returning any match group and its key."""
|
||||
@ -182,15 +192,16 @@ if __name__ == '__main__':
|
||||
else:
|
||||
FILES = get_modified_files(REPO, ARGS)
|
||||
|
||||
ADDRESSES = []
|
||||
|
||||
# Accumulate a sorted list of addresses
|
||||
ADDRESSES = set([])
|
||||
for file in FILES:
|
||||
print(file)
|
||||
addresslist = get_maintainers(file, SECTIONS)
|
||||
if addresslist:
|
||||
ADDRESSES += addresslist
|
||||
recipients = get_maintainers(file, SECTIONS)
|
||||
ADDRESSES |= set(recipients['maintainers'] + recipients['reviewers'] + recipients['lists'])
|
||||
ADDRESSES = list(ADDRESSES)
|
||||
ADDRESSES.sort()
|
||||
|
||||
for address in list(OrderedDict.fromkeys(ADDRESSES)):
|
||||
for address in ADDRESSES:
|
||||
if '<' in address and '>' in address:
|
||||
address = address.split('>', 1)[0] + '>'
|
||||
print(' %s' % address)
|
||||
|
@ -363,6 +363,9 @@ class GitDiffCheck:
|
||||
self.is_newfile = False
|
||||
self.force_crlf = True
|
||||
self.force_notabs = True
|
||||
if self.filename.endswith('.rtf'):
|
||||
self.force_crlf = False
|
||||
self.force_notabs = False
|
||||
if self.filename.endswith('.sh') or \
|
||||
self.filename.startswith('BaseTools/BinWrappers/PosixLike/') or \
|
||||
self.filename.startswith('BaseTools/BinPipWrappers/PosixLike/') or \
|
||||
@ -416,7 +419,7 @@ class GitDiffCheck:
|
||||
self.format_error("didn't find diff hunk marker (@@)")
|
||||
self.line_num += 1
|
||||
elif self.state == PATCH:
|
||||
if self.binary:
|
||||
if self.binary or self.filename.endswith(".rtf"):
|
||||
pass
|
||||
elif line.startswith('-'):
|
||||
pass
|
||||
|
@ -116,63 +116,6 @@ CHAR8 *mFvbAlignmentName[] = {
|
||||
EFI_FVB2_ALIGNMENT_2G_STRING
|
||||
};
|
||||
|
||||
//
|
||||
// This data array will be located at the base of the Firmware Volume Header (FVH)
|
||||
// in the boot block. It must not exceed 14 bytes of code. The last 2 bytes
|
||||
// will be used to keep the FVH checksum consistent.
|
||||
// This code will be run in response to a startup IPI for HT-enabled systems.
|
||||
//
|
||||
#define SIZEOF_STARTUP_DATA_ARRAY 0x10
|
||||
|
||||
UINT8 m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
|
||||
//
|
||||
// EA D0 FF 00 F0 ; far jmp F000:FFD0
|
||||
// 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
|
||||
// 0, 0 ; Checksum Padding
|
||||
//
|
||||
0xEA,
|
||||
0xD0,
|
||||
0xFF,
|
||||
0x0,
|
||||
0xF0,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00
|
||||
};
|
||||
|
||||
UINT8 m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
|
||||
//
|
||||
// EB CE ; jmp short ($-0x30)
|
||||
// ; (from offset 0x0 to offset 0xFFD0)
|
||||
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
|
||||
// 0, 0 ; Checksum Padding
|
||||
//
|
||||
0xEB,
|
||||
0xCE,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00
|
||||
};
|
||||
|
||||
FV_INFO mFvDataInfo;
|
||||
CAP_INFO mCapDataInfo;
|
||||
BOOLEAN mIsLargeFfs = FALSE;
|
||||
@ -1568,12 +1511,6 @@ Returns:
|
||||
EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;
|
||||
INT32 Ia32SecEntryOffset;
|
||||
UINT32 *Ia32ResetAddressPtr;
|
||||
UINT8 *BytePointer;
|
||||
UINT8 *BytePointer2;
|
||||
UINT16 *WordPointer;
|
||||
UINT16 CheckSum;
|
||||
UINT32 IpiVector;
|
||||
UINTN Index;
|
||||
EFI_FFS_FILE_STATE SavedState;
|
||||
BOOLEAN Vtf0Detected;
|
||||
UINT32 FfsHeaderSize;
|
||||
@ -1745,65 +1682,6 @@ if (MachineType == IMAGE_FILE_MACHINE_I386 || MachineType == IMAGE_FILE_MACHINE_
|
||||
Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4);
|
||||
*Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress);
|
||||
DebugMsg (NULL, 0, 9, "update BFV base address in the top FV image", "BFV base address = 0x%llX.", (unsigned long long) FvInfo->BaseAddress);
|
||||
|
||||
//
|
||||
// Update the Startup AP in the FVH header block ZeroVector region.
|
||||
//
|
||||
BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
|
||||
if (FvInfo->Size <= 0x10000) {
|
||||
BytePointer2 = m64kRecoveryStartupApDataArray;
|
||||
} else if (FvInfo->Size <= 0x20000) {
|
||||
BytePointer2 = m128kRecoveryStartupApDataArray;
|
||||
} else {
|
||||
BytePointer2 = m128kRecoveryStartupApDataArray;
|
||||
//
|
||||
// Find the position to place Ap reset vector, the offset
|
||||
// between the position and the end of Fvrecovery.fv file
|
||||
// should not exceed 128kB to prevent Ap reset vector from
|
||||
// outside legacy E and F segment
|
||||
//
|
||||
Status = FindApResetVectorPosition (FvImage, &BytePointer);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Error (NULL, 0, 3000, "Invalid", "FV image does not have enough space to place AP reset vector. The FV image needs to reserve at least 4KB of unused space.");
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
}
|
||||
|
||||
for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {
|
||||
BytePointer[Index] = BytePointer2[Index];
|
||||
}
|
||||
//
|
||||
// Calculate the checksum
|
||||
//
|
||||
CheckSum = 0x0000;
|
||||
WordPointer = (UINT16 *) (BytePointer);
|
||||
for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {
|
||||
CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));
|
||||
WordPointer++;
|
||||
}
|
||||
//
|
||||
// Update the checksum field
|
||||
//
|
||||
WordPointer = (UINT16 *) (BytePointer + SIZEOF_STARTUP_DATA_ARRAY - 2);
|
||||
*WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum);
|
||||
|
||||
//
|
||||
// IpiVector at the 4k aligned address in the top 2 blocks in the PEI FV.
|
||||
//
|
||||
IpiVector = (UINT32) (FV_IMAGES_TOP_ADDRESS - ((UINTN) FvImage->Eof - (UINTN) BytePointer));
|
||||
DebugMsg (NULL, 0, 9, "Startup AP Vector address", "IpiVector at 0x%X", (unsigned) IpiVector);
|
||||
if ((IpiVector & 0xFFF) != 0) {
|
||||
Error (NULL, 0, 3000, "Invalid", "Startup AP Vector address are not 4K aligned, because the FV size is not 4K aligned");
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
IpiVector = IpiVector >> 12;
|
||||
IpiVector = IpiVector & 0xFF;
|
||||
|
||||
//
|
||||
// Write IPI Vector at Offset FvrecoveryFileSize - 8
|
||||
//
|
||||
Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 8);
|
||||
*Ia32ResetAddressPtr = IpiVector;
|
||||
} else if (MachineType == IMAGE_FILE_MACHINE_ARMTHUMB_MIXED) {
|
||||
//
|
||||
// Since the ARM reset vector is in the FV Header you really don't need a
|
||||
@ -4190,83 +4068,6 @@ Returns:
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
FindApResetVectorPosition (
|
||||
IN MEMORY_FILE *FvImage,
|
||||
OUT UINT8 **Pointer
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Find the position in this FvImage to place Ap reset vector.
|
||||
|
||||
Arguments:
|
||||
|
||||
FvImage Memory file for the FV memory image.
|
||||
Pointer Pointer to pointer to position.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_NOT_FOUND - No satisfied position is found.
|
||||
EFI_SUCCESS - The suitable position is return.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_FFS_FILE_HEADER *PadFile;
|
||||
UINT32 Index;
|
||||
EFI_STATUS Status;
|
||||
UINT8 *FixPoint;
|
||||
UINT32 FileLength;
|
||||
|
||||
for (Index = 1; ;Index ++) {
|
||||
//
|
||||
// Find Pad File to add ApResetVector info
|
||||
//
|
||||
Status = GetFileByType (EFI_FV_FILETYPE_FFS_PAD, Index, &PadFile);
|
||||
if (EFI_ERROR (Status) || (PadFile == NULL)) {
|
||||
//
|
||||
// No Pad file to be found.
|
||||
//
|
||||
break;
|
||||
}
|
||||
//
|
||||
// Get Pad file size.
|
||||
//
|
||||
FileLength = GetFfsFileLength(PadFile);
|
||||
FileLength = (FileLength + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1);
|
||||
//
|
||||
// FixPoint must be align on 0x1000 relative to FvImage Header
|
||||
//
|
||||
FixPoint = (UINT8*) PadFile + GetFfsHeaderLength(PadFile);
|
||||
FixPoint = FixPoint + 0x1000 - (((UINTN) FixPoint - (UINTN) FvImage->FileImage) & 0xFFF);
|
||||
//
|
||||
// FixPoint be larger at the last place of one fv image.
|
||||
//
|
||||
while (((UINTN) FixPoint + SIZEOF_STARTUP_DATA_ARRAY - (UINTN) PadFile) <= FileLength) {
|
||||
FixPoint += 0x1000;
|
||||
}
|
||||
FixPoint -= 0x1000;
|
||||
|
||||
if ((UINTN) FixPoint < ((UINTN) PadFile + GetFfsHeaderLength(PadFile))) {
|
||||
//
|
||||
// No alignment FixPoint in this Pad File.
|
||||
//
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((UINTN) FvImage->Eof - (UINTN)FixPoint <= 0x20000) {
|
||||
//
|
||||
// Find the position to place ApResetVector
|
||||
//
|
||||
*Pointer = FixPoint;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
ParseCapInf (
|
||||
IN MEMORY_FILE *InfFile,
|
||||
|
@ -1778,7 +1778,17 @@ WriteSections64 (
|
||||
case R_LARCH_TLS_LD64_HI20:
|
||||
case R_LARCH_TLS_GD_PC_HI20:
|
||||
case R_LARCH_TLS_GD64_HI20:
|
||||
case R_LARCH_32_PCREL:
|
||||
case R_LARCH_RELAX:
|
||||
case R_LARCH_DELETE:
|
||||
case R_LARCH_ALIGN:
|
||||
case R_LARCH_PCREL20_S2:
|
||||
case R_LARCH_CFA:
|
||||
case R_LARCH_ADD6:
|
||||
case R_LARCH_SUB6:
|
||||
case R_LARCH_ADD_ULEB128:
|
||||
case R_LARCH_SUB_ULEB128:
|
||||
case R_LARCH_64_PCREL:
|
||||
//
|
||||
// These types are not used or do not require fixup.
|
||||
//
|
||||
@ -2185,7 +2195,17 @@ WriteRelocations64 (
|
||||
case R_LARCH_TLS_LD64_HI20:
|
||||
case R_LARCH_TLS_GD_PC_HI20:
|
||||
case R_LARCH_TLS_GD64_HI20:
|
||||
case R_LARCH_32_PCREL:
|
||||
case R_LARCH_RELAX:
|
||||
case R_LARCH_DELETE:
|
||||
case R_LARCH_ALIGN:
|
||||
case R_LARCH_PCREL20_S2:
|
||||
case R_LARCH_CFA:
|
||||
case R_LARCH_ADD6:
|
||||
case R_LARCH_SUB6:
|
||||
case R_LARCH_ADD_ULEB128:
|
||||
case R_LARCH_SUB_ULEB128:
|
||||
case R_LARCH_64_PCREL:
|
||||
//
|
||||
// These types are not used or do not require fixup in PE format files.
|
||||
//
|
||||
|
@ -86,6 +86,7 @@ UINT32 mImageSize = 0;
|
||||
UINT32 mOutImageType = FW_DUMMY_IMAGE;
|
||||
BOOLEAN mIsConvertXip = FALSE;
|
||||
BOOLEAN mExportFlag = FALSE;
|
||||
BOOLEAN mNoNxCompat = FALSE;
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
@ -281,6 +282,9 @@ Returns:
|
||||
write export table into PE-COFF.\n\
|
||||
This option can be used together with -e.\n\
|
||||
It doesn't work for other options.\n");
|
||||
fprintf (stdout, " --nonxcompat Do not set the IMAGE_DLLCHARACTERISTICS_NX_COMPAT bit \n\
|
||||
of the optional header in the PE header even if the \n\
|
||||
requirements are met.\n");
|
||||
fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");
|
||||
fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");
|
||||
fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");
|
||||
@ -441,6 +445,59 @@ Returns:
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Checks if the Pe image is nxcompat compliant.
|
||||
|
||||
Must meet the following conditions:
|
||||
1. The PE is 64bit
|
||||
2. The section alignment is evenly divisible by 4k
|
||||
3. No section is writable and executable.
|
||||
|
||||
@param PeHdr - The PE header
|
||||
|
||||
@retval TRUE - The PE is nx compat compliant
|
||||
@retval FALSE - The PE is not nx compat compliant
|
||||
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
IsNxCompatCompliant (
|
||||
EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr
|
||||
)
|
||||
{
|
||||
EFI_IMAGE_SECTION_HEADER *SectionHeader;
|
||||
UINT32 Index;
|
||||
UINT32 Mask;
|
||||
|
||||
// Must have an optional header to perform verification
|
||||
if (PeHdr->Pe32.FileHeader.SizeOfOptionalHeader == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Verify PE is 64 bit
|
||||
if (!(PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Verify Section Alignment is divisible by 4K
|
||||
if (!((PeHdr->Pe32Plus.OptionalHeader.SectionAlignment % EFI_PAGE_SIZE) == 0)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Verify sections are not Write & Execute
|
||||
Mask = EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_MEM_WRITE;
|
||||
SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32Plus.OptionalHeader) + PeHdr->Pe32Plus.FileHeader.SizeOfOptionalHeader);
|
||||
for (Index = 0; Index < PeHdr->Pe32Plus.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
|
||||
if ((SectionHeader->Characteristics & Mask) == Mask) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Passed all requirements, return TRUE
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
SetHiiResourceHeader (
|
||||
UINT8 *HiiBinData,
|
||||
@ -1452,6 +1509,13 @@ Returns:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stricmp (argv[0], "--nonxcompat") == 0) {
|
||||
mNoNxCompat = TRUE;
|
||||
argc --;
|
||||
argv ++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argv[0][0] == '-') {
|
||||
Error (NULL, 0, 1000, "Unknown option", argv[0]);
|
||||
goto Finish;
|
||||
@ -2458,6 +2522,11 @@ Returns:
|
||||
TEImageHeader.BaseOfCode = Optional64->BaseOfCode;
|
||||
TEImageHeader.ImageBase = (UINT64) (Optional64->ImageBase);
|
||||
|
||||
// Set NxCompat flag
|
||||
if (IsNxCompatCompliant (PeHdr) && !mNoNxCompat) {
|
||||
Optional64->DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NX_COMPAT;
|
||||
}
|
||||
|
||||
if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
|
||||
TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
|
||||
TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
|
||||
|
@ -1144,5 +1144,16 @@ typedef struct {
|
||||
#define R_LARCH_TLS_LD64_HI20 96
|
||||
#define R_LARCH_TLS_GD_PC_HI20 97
|
||||
#define R_LARCH_TLS_GD64_HI20 98
|
||||
#define R_LARCH_RELAX 99
|
||||
#define R_LARCH_32_PCREL 99
|
||||
#define R_LARCH_RELAX 100
|
||||
#define R_LARCH_DELETE 101
|
||||
#define R_LARCH_ALIGN 102
|
||||
#define R_LARCH_PCREL20_S2 103
|
||||
#define R_LARCH_CFA 104
|
||||
#define R_LARCH_ADD6 105
|
||||
#define R_LARCH_SUB6 106
|
||||
#define R_LARCH_ADD_ULEB128 107
|
||||
#define R_LARCH_SUB_ULEB128 108
|
||||
#define R_LARCH_64_PCREL 109
|
||||
|
||||
#endif /* !_SYS_ELF_COMMON_H_ */
|
||||
|
@ -281,10 +281,10 @@ def DoInclude(Source, Indent='', IncludePathList=[], LocalSearchPath=None, Inclu
|
||||
F = File.readlines()
|
||||
break
|
||||
else:
|
||||
EdkLogger.warn("Trim", "Failed to find include file %s" % Source)
|
||||
EdkLogger.error("Trim", "Failed to find include file %s" % Source)
|
||||
return []
|
||||
except:
|
||||
EdkLogger.warn("Trim", FILE_OPEN_FAILURE, ExtraData=Source)
|
||||
EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Source)
|
||||
return []
|
||||
|
||||
|
||||
|
@ -1,381 +1,179 @@
|
||||
{\rtf1\adeflang1025\ansi\ansicpg1252\uc2\adeff0\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1033\deflangfe2052\themelang1033\themelangfe2052\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times};}
|
||||
{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New{\*\falt Courier New};}{\f13\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}\'cb\'ce\'cc\'e5{\*\falt SimSun};}
|
||||
{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri{\*\falt Century Gothic};}
|
||||
{\f39\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma{\*\falt Times New Roman};}{\f41\fbidi \fmodern\fcharset0\fprq1{\*\panose 020b0609020204030204}Consolas;}
|
||||
{\f43\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Verdana{\*\falt Verdana};}{\f113\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}@\'cb\'ce\'cc\'e5;}
|
||||
{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times};}{\fdbmajor\f31501\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}\'cb\'ce\'cc\'e5{\*\falt SimSun};}
|
||||
{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times};}
|
||||
{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times};}{\fdbminor\f31505\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}\'cb\'ce\'cc\'e5{\*\falt SimSun};}
|
||||
{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri{\*\falt Century Gothic};}{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times};}
|
||||
{\f258\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times};}{\f259\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times};}{\f261\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times};}
|
||||
{\f262\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times};}{\f263\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times};}{\f264\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times};}
|
||||
{\f265\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times};}{\f266\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times};}{\f278\fbidi \fmodern\fcharset238\fprq1 Courier New CE{\*\falt Courier New};}
|
||||
{\f279\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr{\*\falt Courier New};}{\f281\fbidi \fmodern\fcharset161\fprq1 Courier New Greek{\*\falt Courier New};}{\f282\fbidi \fmodern\fcharset162\fprq1 Courier New Tur{\*\falt Courier New};}
|
||||
{\f283\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew){\*\falt Courier New};}{\f284\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic){\*\falt Courier New};}{\f285\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic{\*\falt Courier New};}
|
||||
{\f286\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese){\*\falt Courier New};}{\f390\fbidi \fnil\fcharset0\fprq2 SimSun Western{\*\falt SimSun};}{\f598\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}
|
||||
{\f599\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}{\f601\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f602\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f605\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}
|
||||
{\f606\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}{\f628\fbidi \fswiss\fcharset238\fprq2 Calibri CE{\*\falt Century Gothic};}{\f629\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr{\*\falt Century Gothic};}
|
||||
{\f631\fbidi \fswiss\fcharset161\fprq2 Calibri Greek{\*\falt Century Gothic};}{\f632\fbidi \fswiss\fcharset162\fprq2 Calibri Tur{\*\falt Century Gothic};}{\f635\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic{\*\falt Century Gothic};}
|
||||
{\f636\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese){\*\falt Century Gothic};}{\f648\fbidi \fswiss\fcharset238\fprq2 Tahoma CE{\*\falt Times New Roman};}{\f649\fbidi \fswiss\fcharset204\fprq2 Tahoma Cyr{\*\falt Times New Roman};}
|
||||
{\f651\fbidi \fswiss\fcharset161\fprq2 Tahoma Greek{\*\falt Times New Roman};}{\f652\fbidi \fswiss\fcharset162\fprq2 Tahoma Tur{\*\falt Times New Roman};}{\f653\fbidi \fswiss\fcharset177\fprq2 Tahoma (Hebrew){\*\falt Times New Roman};}
|
||||
{\f654\fbidi \fswiss\fcharset178\fprq2 Tahoma (Arabic){\*\falt Times New Roman};}{\f655\fbidi \fswiss\fcharset186\fprq2 Tahoma Baltic{\*\falt Times New Roman};}{\f656\fbidi \fswiss\fcharset163\fprq2 Tahoma (Vietnamese){\*\falt Times New Roman};}
|
||||
{\f657\fbidi \fswiss\fcharset222\fprq2 Tahoma (Thai){\*\falt Times New Roman};}{\f668\fbidi \fmodern\fcharset238\fprq1 Consolas CE;}{\f669\fbidi \fmodern\fcharset204\fprq1 Consolas Cyr;}{\f671\fbidi \fmodern\fcharset161\fprq1 Consolas Greek;}
|
||||
{\f672\fbidi \fmodern\fcharset162\fprq1 Consolas Tur;}{\f675\fbidi \fmodern\fcharset186\fprq1 Consolas Baltic;}{\f676\fbidi \fmodern\fcharset163\fprq1 Consolas (Vietnamese);}{\f688\fbidi \fswiss\fcharset238\fprq2 Verdana CE{\*\falt Verdana};}
|
||||
{\f689\fbidi \fswiss\fcharset204\fprq2 Verdana Cyr{\*\falt Verdana};}{\f691\fbidi \fswiss\fcharset161\fprq2 Verdana Greek{\*\falt Verdana};}{\f692\fbidi \fswiss\fcharset162\fprq2 Verdana Tur{\*\falt Verdana};}
|
||||
{\f695\fbidi \fswiss\fcharset186\fprq2 Verdana Baltic{\*\falt Verdana};}{\f696\fbidi \fswiss\fcharset163\fprq2 Verdana (Vietnamese){\*\falt Verdana};}{\f1390\fbidi \fnil\fcharset0\fprq2 @\'cb\'ce\'cc\'e5 Western;}
|
||||
{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times};}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times};}
|
||||
{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times};}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times};}
|
||||
{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times};}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times};}
|
||||
{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times};}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times};}
|
||||
{\fdbmajor\f31520\fbidi \fnil\fcharset0\fprq2 SimSun Western{\*\falt SimSun};}{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}
|
||||
{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}
|
||||
{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times};}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times};}
|
||||
{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times};}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times};}
|
||||
{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times};}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times};}
|
||||
{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times};}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times};}
|
||||
{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times};}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times};}
|
||||
{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times};}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times};}
|
||||
{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times};}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times};}
|
||||
{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times};}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times};}
|
||||
{\fdbminor\f31560\fbidi \fnil\fcharset0\fprq2 SimSun Western{\*\falt SimSun};}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE{\*\falt Century Gothic};}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr{\*\falt Century Gothic};}
|
||||
{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek{\*\falt Century Gothic};}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur{\*\falt Century Gothic};}
|
||||
{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic{\*\falt Century Gothic};}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese){\*\falt Century Gothic};}
|
||||
{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times};}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times};}
|
||||
{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times};}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times};}
|
||||
{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times};}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times};}
|
||||
{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times};}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times};}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;
|
||||
\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;
|
||||
\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red8\green96\blue168;\red0\green127\blue127;}{\*\defchp \fs21\kerning2\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap
|
||||
\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang1033\langfe2052\loch\f43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 \snext0 \sqformat \spriority0 Normal;}{\s1\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang1033\langfe2052\loch\f43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 \sbasedon0 \snext0 \slink15 \sqformat heading 1;}{\s2\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025
|
||||
\ltrch\fcs0 \fs24\lang1033\langfe2052\loch\f43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 \sbasedon0 \snext0 \slink16 \sqformat heading 2;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
|
||||
\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv
|
||||
\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs21\alang1025 \ltrch\fcs0 \fs21\lang1033\langfe2052\kerning2\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp2052
|
||||
\snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \ab\af0\afs44 \ltrch\fcs0 \b\f43\fs44\kerning44 \sbasedon10 \slink1 \slocked \spriority9 Heading 1 Char;}{\*\cs16 \additive \rtlch\fcs1 \ab\af0\afs32 \ltrch\fcs0
|
||||
\b\fs32\kerning0\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink2 \slocked Heading 2 Char;}{\*\cs17 \additive \rtlch\fcs1 \af0\afs16 \ltrch\fcs0 \fs16 \sbasedon10 \ssemihidden \sunhideused \styrsid4815795 annotation reference;}{
|
||||
\s18\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs20\alang1025 \ltrch\fcs0 \fs20\lang1033\langfe2052\loch\f43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052
|
||||
\sbasedon0 \snext18 \slink19 \ssemihidden \sunhideused \styrsid4815795 annotation text;}{\*\cs19 \additive \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f43\fs20\lang0\langfe2052\kerning0\langnp0\langfenp2052
|
||||
\sbasedon10 \slink18 \slocked \ssemihidden \styrsid4815795 Comment Text Char;}{\s20\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs20\alang1025 \ltrch\fcs0
|
||||
\b\fs20\lang1033\langfe2052\loch\f43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 \sbasedon18 \snext18 \slink21 \ssemihidden \sunhideused \styrsid4815795 annotation subject;}{\*\cs21 \additive \rtlch\fcs1 \ab\af0\afs20 \ltrch\fcs0
|
||||
\b\f43\fs20\lang0\langfe2052\kerning0\langnp0\langfenp2052 \sbasedon19 \slink20 \slocked \ssemihidden \styrsid4815795 Comment Subject Char;}{\s22\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af39\afs16\alang1025 \ltrch\fcs0
|
||||
\fs16\lang1033\langfe2052\loch\f39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp2052 \sbasedon0 \snext22 \slink23 \ssemihidden \sunhideused \styrsid4815795 Balloon Text;}{\*\cs23 \additive \rtlch\fcs1 \af39\afs16 \ltrch\fcs0
|
||||
\f39\fs16\lang0\langfe2052\kerning0\langnp0\langfenp2052 \sbasedon10 \slink22 \slocked \ssemihidden \styrsid4815795 Balloon Text Char;}{\s24\ql \li0\ri20\sb60\sa60\sl-200\slmult0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin20\lin0\itap0
|
||||
\rtlch\fcs1 \af0\afs16\alang1025 \ltrch\fcs0 \fs16\cf1\lang1033\langfe1033\loch\f43\hich\af43\dbch\af13\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext24 \spriority0 \styrsid6636700 CellBodyLeft;}{\*\cs25 \additive \b\f2\cf13 \spriority0 \styrsid6636700
|
||||
CodeCharacter;}{\*\ts26\tsrowd\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10
|
||||
\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv
|
||||
\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe2052\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp2052
|
||||
\sbasedon11 \snext26 \spriority59 \styrsid6636700 Table Grid;}}{\*\revtbl {Unknown;}{Zhu, Yonghong;}}{\*\rsidtbl \rsid1120999\rsid3954098\rsid4815795\rsid4999604\rsid5318420\rsid5911148\rsid6184429\rsid6636700\rsid8089322\rsid8459339\rsid8600807\rsid12198464\rsid12521351\rsid14966438
|
||||
\rsid15026228\rsid15604690\rsid16255639\rsid16399512}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Zhu, Yonghong}{\creatim\yr2011\mo7\dy18\hr16\min14}
|
||||
{\revtim\yr2016\mo8\dy9\hr10\min26}{\version11}{\edmins23}{\nofpages4}{\nofwords842}{\nofchars4801}{\nofcharsws5632}{\vern57441}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}
|
||||
\paperw12240\paperh15840\margl1800\margr1800\margt1440\margb1440\gutter0\ltrsect
|
||||
\deftab360\widowctrl\ftnbj\aenddoc\revisions\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120
|
||||
\dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot15604690 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang
|
||||
{\pntxta \hich .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta \hich .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta \hich .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta \hich )}}{\*\pnseclvl5
|
||||
\pndec\pnstart1\pnindent720\pnhang {\pntxtb \hich (}{\pntxta \hich )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb \hich (}{\pntxta \hich )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb \hich (}{\pntxta \hich )}}{\*\pnseclvl8
|
||||
\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb \hich (}{\pntxta \hich )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb \hich (}{\pntxta \hich )}}\pard\plain \ltrpar\s2\ql \li-1440\ri0\sb400\sa60\sl-340\slmult0
|
||||
\keep\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin-1440\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \ab\af43\afs28 \ltrch\fcs0
|
||||
\b\fs28\cf17\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Name
|
||||
\par }\pard\plain \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af43\afs18
|
||||
\ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 GenFw.exe \hich\f43 \endash \loch\f43 build a UEFI image or other image.
|
||||
\par }\pard\plain \ltrpar\s2\ql \li-1440\ri0\sb400\sa60\sl-340\slmult0\keep\keepn\nowidctlpar\tx1440\wrapdefault\faauto\outlinelevel1\rin0\lin-1440\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \ab\af43\afs28 \ltrch\fcs0 \b\fs28\cf17\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Synopsis
|
||||
\par }\pard\plain \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \ab\af43\afs18
|
||||
\ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 GenFw.exe }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid12521351 \hich\af43\dbch\af31505\loch\f43 -r | }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0
|
||||
\b\fs18\cf1\insrsid3954098 \hich\af43\dbch\af31505\loch\f43 -o <OutputFile> [-e }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid5318420 \hich\af43\dbch\af31505\loch\f43 <}{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid3954098
|
||||
\hich\af43\dbch\af31505\loch\f43 EfiType}{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid5318420 \hich\af43\dbch\af31505\loch\f43 >}{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid3954098 \hich\af43\dbch\af31505\loch\f43
|
||||
] [-c | -t | -l | -u | -b | -z | -s }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid5318420 \hich\af43\dbch\af31505\loch\f43 <}{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid3954098 \hich\af43\dbch\af31505\loch\f43 TimeDate}{
|
||||
\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid5318420 \hich\af43\dbch\af31505\loch\f43 >}{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid3954098 \hich\af43\dbch\af31505\loch\f43 | -m | -j | }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0
|
||||
\b\fs18\cf1\insrsid3954098\charrsid3954098 \hich\af43\dbch\af31505\loch\f43 --hiipackage}{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid3954098 \hich\af43\dbch\af31505\loch\f43 | --}{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0
|
||||
\b\fs18\cf1\insrsid3954098\charrsid3954098 \hich\af43\dbch\af31505\loch\f43 hiibinpackage}{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid3954098 \hich\af43\dbch\af31505\loch\f43 ]}{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0
|
||||
\b\fs18\cf1\insrsid12521351 \hich\af43\dbch\af31505\loch\f43 [-a] [-p]}{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid3954098
|
||||
\hich\af43\dbch\af31505\loch\f43 <Input}{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 File}{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid3954098 \hich\af43\dbch\af31505\loch\f43 >}{
|
||||
\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339
|
||||
\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid16399512 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid16399512 \hich\af43\dbch\af31505\loch\f43 GenFw.exe \hich\f43 \endash \loch\f43 h
|
||||
\par \hich\af43\dbch\af31505\loch\f43 GenFw.exe --version}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16399512\charrsid8089322
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af0\afs18 \ltrch\fcs0 \f0\fs18\cf1\insrsid16399512
|
||||
\par }\pard\plain \ltrpar\s2\ql \li-1440\ri0\sb400\sa60\sl-340\slmult0\keep\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin-1440\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \ab\af43\afs28 \ltrch\fcs0 \b\fs28\cf17\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Description
|
||||
\par }\pard\plain \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af43\afs18
|
||||
\ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Genfw is mainly used to process PE32 image to get the expected image data or image file. PE32 is a general-purpose image format that contains, among other information, data
|
||||
\hich\af43\dbch\af31505\loch\f43
|
||||
identifying the target environment for execution of the image. This utility can modify the standard PE32 image to create UEFI image with EFI subsystem type, PI Terse Executable image with the compact TE image header, zero its dubug data or reset its time
|
||||
\hich\af43\dbch\af31505\loch\f43 s\hich\af43\dbch\af31505\loch\f43
|
||||
tamp. It can also extract PE32 image data to create bin file, extract PE32 image data section to create Acpi table image, or dump PI TE image header information. It can also parse the text MicroCode definition file to create the MicroCode binary image, me
|
||||
\hich\af43\dbch\af31505\loch\f43 r\hich\af43\dbch\af31505\loch\f43 ge (concatenate) several MicroCode binary images into a single file by pad value and alignment requirement. This tool also supports the override the input file with the output contents.
|
||||
{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033\deflangfe1033\deftab360{\fonttbl{\f0\fswiss\fprq2\fcharset0 Verdana;}{\f1\froman\fprq2\fcharset0 Times New Roman;}{\f2\fmodern\fprq1\fcharset0 Courier New;}{\f3\fmodern\fprq1\fcharset0 Consolas;}}
|
||||
{\colortbl ;\red8\green96\blue168;\red0\green0\blue0;\red0\green127\blue127;\red128\green0\blue0;\red0\green0\blue255;}
|
||||
{\stylesheet{ Normal;}{\s1 heading 1;}{\s2 heading 2;}}
|
||||
{\*\generator Riched20 10.0.22621}{\*\mmathPr\mnaryLim0\mdispDef1\mwrapIndent1440 }\viewkind4\uc1
|
||||
\pard\keep\keepn\nowidctlpar\s2\li-1440\sb400\sa60\sl-340\slmult0\cf1\b\f0\fs28 Name\par
|
||||
|
||||
\par }\pard\plain \ltrpar\s2\ql \li-1440\ri0\sb400\sa60\sl-340\slmult0\keep\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin-1440\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \ab\af43\afs28 \ltrch\fcs0 \b\fs28\cf17\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Options
|
||||
\par }\pard\plain \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af43\afs18
|
||||
\ltrch\fcs0 \fs18\cf1\insrsid15026228\charrsid12198464 \hich\af43\dbch\af31505\loch\f43 If no options ar}{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid15026228 \hich\af43\dbch\af31505\loch\f43 e specified, tool prints usage.}{\rtlch\fcs1
|
||||
\ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid4815795
|
||||
\par }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Filename1 [FilenameN]
|
||||
\par }\pard \ltrpar\ql \li360\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin360\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43
|
||||
Input PE/PE32+ image, or TE image, or MicroCode Txt file, or MicroCode bin file, or hii binary packages.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -o FileName, --outputfile FileName
|
||||
\par }\pard \ltrpar\ql \li360\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin360\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43
|
||||
The EFI image, TeImage, AcpiImage, MicroBin, hii package lists file or other modified PE image\hich\af43\dbch\af31505\loch\f43 will be created.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -e EFI_FILETYPE, --efiImage EFI_FILETYPE
|
||||
\par }\pard \ltrpar\ql \li360\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin360\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43
|
||||
Create Efi Image. EFI_FILETYPE is one of BASE, SEC, PEI_CORE, PEIM, DXE_CORE, SMM_CORE, DXE_DRIVER, UEFI_APPLICATION, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER, DXE_SMM_DRIVER, SECURITY_CORE,\hich\af43\dbch\af31505\loch\f43
|
||||
COMBINED_PEIM_DRIVER, PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER, APPLICATION, SAL_RT_DRIVER to support all module types.}{\rtlch\fcs1 \af0\afs18 \ltrch\fcs0 \f0\fs18\cf1\insrsid8459339
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -c, --acpi
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Create Acpi table.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -t, --terse
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Create Te Image.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -u, --dump
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Dump TeImage Header.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -z, --zero
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43
|
||||
Zero the Debug Data Fields in the PE input image file. It also zeros the time stamp fields.}{\rtlch\fcs1 \af0\afs18 \ltrch\fcs0 \f0\fs18\cf1\insrsid8459339
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -b, --exe2bin
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Convert the input EXE to the output BIN file.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -l, --stripped
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Strip off the relocation information data from PE or TE image.}{
|
||||
\rtlch\fcs1 \af0\afs18 \ltrch\fcs0 \f0\fs18\cf1\insrsid8459339
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -s timedate, --stamp timed\hich\af43\dbch\af31505\loch\f43 ate
|
||||
\par }\pard \ltrpar\ql \li360\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin360\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 \hich\f43 timedate format is \'93\loch\f43 \hich\f43 yyyy-mm-dd 00:00:00\'94
|
||||
\loch\f43 \hich\f43 . If timedata is set to \'93\loch\f43 \hich\f43 NOW\'94\loch\f43 , current system time is used. The support date scope is 1970-1-1 8:0:0 ~ 2038-1-19 3:14:07.}{\rtlch\fcs1 \af0\afs18 \ltrch\fcs0 \f0\fs18\cf1\insrsid8459339
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -m, --mcifile
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Convert input microcode txt definition file to microcode bin file.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -j, --joi\hich\af43\dbch\af31505\loch\f43 n
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Merge multiple microcode bin files to one file.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -a NUM, --align NUM
|
||||
\par }\pard \ltrpar\ql \li360\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin360\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43
|
||||
NUM is one HEX or DEC format alignment value, which is used to combine multiple microcode bin files.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -p NUM, --pad NUM
|
||||
\par }\pard \ltrpar\ql \li360\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin360\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 NUM is one HEX or DEC format padding value, which is used to combin
|
||||
\hich\af43\dbch\af31505\loch\f43 e multiple microcode bin files.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 --keepexceptiontable
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Don\hich\f43 \rquote \loch\f43 t clear exception table.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 --keepzeropending
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Don\hich\f43 \rquote \loch\f43 t strip zero pending of .reloc.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -r, --replace
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Overwrite the input file with the output content.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -g HiiPackageListGuid, --hiiguid HiiPackageListGuid
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Guid\hich\af43\dbch\af31505\loch\f43
|
||||
is used to specify hii package list guid.}{\rtlch\fcs1 \af0\afs18 \ltrch\fcs0 \f0\fs18\cf1\insrsid8459339
|
||||
\par }{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 --hiipackage }{\rtlch\fcs1 \ab\af0\afs18 \ltrch\fcs0
|
||||
\b\f0\fs18\cf1\insrsid8459339
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43
|
||||
Combine all input binary hii packages into a single package list as the text resource data file (RC file format).
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 --hiibinpackage }{\rtlch\fcs1 \ab\af0\afs18 \ltrch\fcs0
|
||||
\b\f0\fs18\cf1\insrsid8459339
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43
|
||||
Combine all input binary hii packages into a single package list as the binary resource section.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -v, --verbose
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Turn on verbose output with informational messages.
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -d, --debug level
|
||||
\par }{\rtlch\fcs1 \af0\afs18 \ltrch\fcs0 \f0\fs18\cf1\insrsid8459339 \tab }{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Enable debug message with specified level.
|
||||
\par }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 --version
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Show program's version number and exit
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 -h, --help
|
||||
\par }\pard \ltrpar\ql \fi360\li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Show this help message and exit
|
||||
\par }\pard\plain \ltrpar\s2\ql \fi-1440\li0\ri0\sb400\sa60\sl-340\slmult0\keep\keepn\nowidctlpar\tx0\tx1440\wrapdefault\faauto\outlinelevel1\rin0\lin0\itap0\pararsid6636700 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \ab\af43\afs28 \ltrch\fcs0 \b\fs28\cf18\insrsid6636700\charrsid6184429 {\*\bkmkstart OLE_LINK7}{\*\bkmkstart OLE_LINK8}\hich\af43\dbch\af31505\loch\f43
|
||||
Status codes returned}{\rtlch\fcs1 \ab\af43\afs28 \ltrch\fcs0 \b\fs28\cf18\insrsid6636700
|
||||
\par \ltrrow}\trowd \irow0\irowband0\ltrrow\ts26\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10
|
||||
\trftsWidth3\trwWidth8820\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid5911148\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl
|
||||
\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2970\clshdrawnil\clhidemark \cellx2862\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10
|
||||
\cltxlrtb\clftsWidth3\clwWidth5850\clshdrawnil\clhidemark \cellx8712\pard\plain \ltrpar\s24\ql \li0\ri20\sb60\sa60\sl-200\slmult0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin20\lin0\pararsid5911148\yts26 \rtlch\fcs1
|
||||
\af0\afs16\alang1025 \ltrch\fcs0 \fs16\cf1\lang1033\langfe1033\loch\af43\hich\af43\dbch\af13\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0
|
||||
\cs25\b\f2\fs18\cf13\lang1033\langfe2052\kerning2\langfenp2052\insrsid6636700\charrsid8600807 \hich\af2\dbch\af13\loch\f2 STATUS_SUCCESS}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid6636700 \hich\af43\dbch\af13\loch\f43 }{\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0
|
||||
\cs25\b\f2\fs18\cf13\lang1033\langfe2052\kerning2\langfenp2052\insrsid6636700\charrsid4999604 \tab }{\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \cs25\b\f2\fs18\cf13\lang1033\langfe2052\kerning2\langfenp2052\insrsid6636700 0}{\rtlch\fcs1 \ab\af2\afs18
|
||||
\ltrch\fcs0 \cs25\b\f2\fs18\lang1033\langfe2052\kerning2\langfenp2052\insrsid6636700 \cell }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid6636700 \hich\af43\dbch\af13\loch\f43 The action was completed as requested.}{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\kerning2\insrsid6636700 \cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af37\afs20 \ltrch\fcs0 \fs20\insrsid6636700 \trowd \irow0\irowband0\ltrrow\ts26\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb
|
||||
\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10
|
||||
\trftsWidth3\trwWidth8820\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid5911148\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl
|
||||
\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2970\clshdrawnil\clhidemark \cellx2862\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10
|
||||
\cltxlrtb\clftsWidth3\clwWidth5850\clshdrawnil\clhidemark \cellx8712\row \ltrrow}\pard\plain \ltrpar\s24\ql \li0\ri20\sb60\sa60\sl-200\slmult0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin20\lin0\pararsid5911148\yts26 \rtlch\fcs1
|
||||
\af0\afs16\alang1025 \ltrch\fcs0 \fs16\cf1\lang1033\langfe1033\loch\af43\hich\af43\dbch\af13\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \cs25\b\f2\fs18\cf13\kerning2\insrsid6636700\charrsid8600807 \hich\af2\dbch\af13\loch\f2
|
||||
STATUS_ERROR}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid6636700 \hich\af43\dbch\af13\loch\f43 }{\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0 \cs25\b\f2\fs18\cf13\kerning2\insrsid6636700\charrsid4999604 \tab \tab }{\rtlch\fcs1 \ab\af2\afs18 \ltrch\fcs0
|
||||
\cs25\b\f2\fs18\cf13\lang1033\langfe2052\kerning2\langfenp2052\insrsid6636700 \hich\af2\dbch\af13\loch\f2 2}{\rtlch\fcs1 \af41\afs19 \ltrch\fcs0 \cs25\f41\fs19\cf0\lang1033\langfe2052\langfenp2052\insrsid6636700\charrsid8600807 \cell }\pard \ltrpar
|
||||
\s24\ql \li0\ri20\sb60\sa60\sl-200\slmult0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin20\lin0\pararsid16255639\yts26 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe2052\kerning2\langfenp2052\insrsid6636700
|
||||
\hich\af43\dbch\af13\loch\f43 The action failed.\cell }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\intbl\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af37\afs20 \ltrch\fcs0 \fs20\insrsid6636700 \trowd \irow1\irowband1\lastrow \ltrrow\ts26\trleft-108\trbrdrt\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10
|
||||
\trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10
|
||||
\trftsWidth3\trwWidth8820\trftsWidthB3\trftsWidthA3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid5911148\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl
|
||||
\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftsWidth3\clwWidth2970\clshdrawnil\clhidemark \cellx2862\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10
|
||||
\cltxlrtb\clftsWidth3\clwWidth5850\clshdrawnil\clhidemark \cellx8712\row }\pard\plain \ltrpar\s2\ql \li-1440\ri0\sb400\sa60\sl-340\slmult0\keep\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin-1440\itap0 \rtlch\fcs1 \af0\afs24\alang1025
|
||||
\ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \ab\af43\afs28 \ltrch\fcs0 \b\fs28\cf17\insrsid8459339 {\*\bkmkend OLE_LINK7}{\*\bkmkend OLE_LINK8}\hich\af43\dbch\af31505\loch\f43 Example
|
||||
\pard\nowidctlpar\sb200\cf2\b0\fs18 GenFw.exe \endash build a UEFI image or other image.\par
|
||||
|
||||
\par }\pard\plain \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af43\afs18
|
||||
\ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 1. Generate Efi image with the input PE image, module type and the output file name.
|
||||
\par }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 GenFw \hich\f43 \endash \loch\f43 e PEI_CORE PeiMain.dll \hich\f43 \endash \loch\f43 o PeiMain.efi
|
||||
\par }{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 2. Generate Te image with the input PE image and the output file name.
|
||||
\par }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 GenFw \hich\f43 \endash \loch\f43 t PeiMain.dll \hich\f43 \endash \loch\f43 o PeiMain.te
|
||||
\par }{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 3. Generate acpi tab\hich\af43\dbch\af31505\loch\f43 le image with the input PE image and the output file name.
|
||||
\par }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 GenFw \hich\f43 \endash \loch\f43 c Facs.dll \hich\f43 \endash \loch\f43 o Facs.acpi
|
||||
\par }{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 4. Dump TeImage Header with the input Te Image and the output file name.
|
||||
\par }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 GenFw \hich\f43 \endash \loch\f43 u PeiMain.te \hich\f43 \endash \loch\f43 o PeiMain.teheader
|
||||
\par }{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 5. Modify PeImage by zero its debug data.
|
||||
\par }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 GenFw \hich\f43 \endash \loch\f43 z Pe\hich\af43\dbch\af31505\loch\f43 iMain.dll \hich\f43 \endash \loch\f43 o Peimain.zero
|
||||
\par }{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 6. Modify PeImage by set new timestamp and override the input image without the output file name.
|
||||
\par }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 GenFw \hich\f43 \endash \loch\f43 \hich\f43 s \'93\loch\f43 \hich\f43 2007-8-16 16:06:32\'94\loch\f43 PeiMain.dll \hich\f43 \endash \loch\f43 r
|
||||
\par }{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 7. Extract bin image from PeImage.
|
||||
\par }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 GenFw \hich\f43 \endash \loch\f43 b PeiMain.dll \hich\f43 \endash \loch\f43 o PeiMain.bin
|
||||
\par }{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 8. Generate the \hich\af43\dbch\af31505\loch\f43 microcode binary file from the micro code txt file.
|
||||
\par }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 GenFw \hich\f43 \endash \loch\f43 m Mci.txt \hich\f43 \endash \loch\f43 o Mci.bin
|
||||
\par }{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 9. Merge the multiple mci binary files to one file.
|
||||
\par }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 GenFw \hich\f43 \endash \loch\f43 j Mci.bin1 Mci.bin2 Mci.bin3 \hich\f43 \endash \loch\f43 a 32 \hich\f43 \endash \loch\f43 p 0xFF \hich\f43 \endash
|
||||
\loch\f43 o Mci.bin
|
||||
\par }{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 10. Generate the text resource file (RC format) based on all input binary HII packages and their package list guid.
|
||||
\par }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 GenFw \hich\f43 \endash \loch\f43 o SampleHii.rc \hich\f43 \endash \loch\f43 g D49D2EB0-44D5-4621-9FD6-1A92C9109B99 \hich\f43 \endash \loch\f43
|
||||
hiipackage SampleStr.hpk SampleVfr.hpk}{\rtlch\fcs1 \ab\af0\afs18 \ltrch\fcs0 \b\f0\fs18\cf1\insrsid8459339
|
||||
\par }{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 11. Generate the binary resource secti\hich\af43\dbch\af31505\loch\f43 on based on all input binary HII packages and their package list guid.}{\rtlch\fcs1
|
||||
\af0\afs18 \ltrch\fcs0 \f0\fs18\cf1\insrsid8459339
|
||||
\par }{\rtlch\fcs1 \ab\af43\afs18 \ltrch\fcs0 \b\fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 GenFw \hich\f43 \endash \loch\f43 o SampleHii.bin \hich\f43 \endash \loch\f43 g D49D2EB0-44D5-4621-9FD6-1A92C9109B99 \hich\f43 \endash \loch\f43
|
||||
hiibinpackage SampleStr.hpk SampleVfr.hpk}{\rtlch\fcs1 \ab\af0\afs18 \ltrch\fcs0 \b\f0\fs18\cf1\insrsid8459339
|
||||
\par }\pard\plain \ltrpar\s2\ql \li-1440\ri0\sb400\sa60\sl-340\slmult0\keep\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin-1440\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \ab\af43\afs28 \ltrch\fcs0 \b\fs28\cf17\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Bugs
|
||||
\par }\pard\plain \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af43\afs18
|
||||
\ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 No known bugs.
|
||||
\par \hich\af43\dbch\af31505\loch\f43 Report bugs to }{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\revised\lang1033\langfe1033\revauth1\revdttm1195920026\langfenp1033\insrsid14966438\charrsid14420013 \hich\af43\dbch\af31505\loch\f43 edk2-
|
||||
\hich\af43\dbch\af31505\loch\f43 devel\hich\af43\dbch\af31505\loch\f43 @lists.01.\hich\af43\dbch\af31505\loch\f43 org}{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \deleted\fs18\cf1\revauthdel1\revdttmdel1195920026\insrsid8459339\delrsid14966438
|
||||
\hich\af43\dbch\af31505\loch\f43 edk2-buildtools-devel@lists.sourceforge.net}{\rtlch\fcs1 \af0\afs18 \ltrch\fcs0 \f0\fs18\cf1\insrsid8459339
|
||||
\par }\pard\plain \ltrpar\s2\ql \li-1440\ri0\sb400\sa60\sl-340\slmult0\keep\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin-1440\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \ab\af43\afs28 \ltrch\fcs0 \b\fs28\cf17\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 Files
|
||||
\par }\pard\plain \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af43\afs18
|
||||
\ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 None
|
||||
\par }\pard\plain \ltrpar\s2\ql \li-1440\ri0\sb400\sa60\sl-340\slmult0\keep\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin-1440\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \ab\af43\afs28 \ltrch\fcs0 \b\fs28\cf17\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 See also
|
||||
\par }\pard\plain \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af43\afs18
|
||||
\ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 None
|
||||
\par }\pard\plain \ltrpar\s2\ql \li-1440\ri0\sb400\sa60\sl-340\slmult0\keep\keepn\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin-1440\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \ab\af43\afs28 \ltrch\fcs0 \b\fs28\cf17\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 License
|
||||
\par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe2052\loch\af43\hich\af43\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0
|
||||
\fs18\cf1\insrsid15604690 \hich\af43\dbch\af31505\loch\f43 Copyright (c) 2007 - 2011}{\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 , Intel Corporation. All rights reserved.
|
||||
\par \hich\af43\dbch\af31505\loch\f43 This program and the accompanying materials are licensed and made available
|
||||
\par \hich\af43\dbch\af31505\loch\f43 under the terms and conditions of the BSD License which accompanies this
|
||||
\par \hich\af43\dbch\af31505\loch\f43 distr\hich\af43\dbch\af31505\loch\f43 ibution. The full text of the license may be found at
|
||||
\par \hich\af43\dbch\af31505\loch\f43 http://opensource.org/licenses/bsd-license.php
|
||||
\par
|
||||
\par \hich\af43\dbch\af31505\loch\f43 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
\par }\pard \ltrpar\ql \li0\ri0\sb200\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af43\afs18 \ltrch\fcs0 \fs18\cf1\insrsid8459339 \hich\af43\dbch\af31505\loch\f43 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
\pard\keep\keepn\nowidctlpar\s2\li-1440\sb400\sa60\sl-340\slmult0\tx1440\cf1\b\fs28 Synopsis\par
|
||||
|
||||
\par }{\rtlch\fcs1 \af0\afs18 \ltrch\fcs0 \f0\fs18\insrsid8459339
|
||||
\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
|
||||
9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad
|
||||
5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6
|
||||
b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0
|
||||
0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6
|
||||
a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f
|
||||
c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512
|
||||
0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462
|
||||
a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865
|
||||
6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b
|
||||
4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b
|
||||
4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210030dd4329a8060000a41b0000160000007468656d652f7468656d652f
|
||||
7468656d65312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87
|
||||
615b8116d8a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad
|
||||
79482a9c0498f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b
|
||||
5d8a314d3c94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab
|
||||
999fb7b4717509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9
|
||||
699640f6719e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd586
|
||||
8b37a088d1e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d6
|
||||
0cf03ac1a5193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f
|
||||
9e7ef3f2d117d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be
|
||||
15c308d3f28acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a9979
|
||||
3849c26ae66252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d
|
||||
32a423279a668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2a
|
||||
f074481847bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86
|
||||
e877f0034e16bafb0e258ebb4faf06b769e888340b103d331115bebc4eb813bf83291b63624a0d1475a756c734f9bbc2cd28546ecbe1e20a3794ca175f3fae90
|
||||
fb6d2dd99bb07b55e5ccf68942bd0877b23c77b908e8db5f9db7f024d9239010f35bd4bbe2fcae387bfff9e2bc289f2fbe24cfaa301468dd8bd846dbb4ddf1c2
|
||||
ae7b4c191ba8292337a469bc25ec3d411f06f53a73e224c5292c8de0516732307070a1c0660d125c7d44553488700a4d7bddd3444299910e254ab984c3a219ae
|
||||
a4adf1d0f82b7bd46cea4388ad1c12ab5d1ed8e1153d9c9f350a3246aad01c6873462b9ac05999ad5cc988826eafc3acae853a33b7ba11cd1445875ba1b236b1
|
||||
399483c90bd560b0b0263435085a21b0f22a9cf9356b38ec6046026d77eba3dc2dc60b17e92219e180643ed27acffba86e9c94c7ca9c225a0f1b0cfae0788ad5
|
||||
4adc5a9aec1b703b8b93caec1a0bd8e5de7b132fe5113cf312503b998e2c2927274bd051db6b35979b1ef271daf6c6704e86c73805af4bdd476216c26593af84
|
||||
0dfb5393d964f9cc9bad5c313709ea70f561ed3ea7b053075221d51696910d0d339585004b34272bff7213cc7a510a5454a3b349b1b206c1f0af490176745d4b
|
||||
c663e2abb2b34b23da76f6352ba57ca2881844c1111ab189d8c7e07e1daaa04f40255c77988aa05fe06e4e5bdb4cb9c5394bbaf28d98c1d971ccd20867e556a7
|
||||
689ec9166e0a522183792b8907ba55ca6e943bbf2a26e52f48957218ffcf54d1fb09dc3eac04da033e5c0d0b8c74a6b43d2e54c4a10aa511f5fb021a07533b20
|
||||
5ae07e17a621a8e082dafc17e450ffb739676998b48643a4daa7211214f623150942f6a02c99e83b85583ddbbb2c4996113211551257a656ec1139246ca86be0
|
||||
aadedb3d1441a89b6a929501833b197fee7b9641a3503739e57c732a59b1f7da1cf8a73b1f9bcca0945b874d4393dbbf10b1680f66bbaa5d6f96e77b6f59113d
|
||||
316bb31a795600b3d256d0cad2fe354538e7566b2bd69cc6cbcd5c38f0e2bcc63058344429dc2121fd07f63f2a7c66bf76e80d75c8f7a1b622f878a18941d840
|
||||
545fb28d07d205d20e8ea071b283369834296bdaac75d256cb37eb0bee740bbe278cad253b8bbfcf69eca23973d939b97891c6ce2cecd8da8e2d343578f6648a
|
||||
c2d0383fc818c798cf64e52f597c740f1cbd05df0c264c49134cf09d4a60e8a107260f20f92d47b374e32f000000ffff0300504b030414000600080000002100
|
||||
0dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f7
|
||||
8277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89
|
||||
d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd500
|
||||
1996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0f
|
||||
bfff0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6
|
||||
a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a
|
||||
0000001c00000000000000000000000000190200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d00140006000800000021
|
||||
0030dd4329a8060000a41b00001600000000000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d001400060008
|
||||
00000021000dd1909fb60000001b0100002700000000000000000000000000b20900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000ad0a00000000}
|
||||
{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d
|
||||
617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
|
||||
6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
|
||||
656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
|
||||
{\*\latentstyles\lsdstimax371\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdlocked0 heading 1;\lsdqformat1 \lsdlocked0 heading 2;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;
|
||||
\lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdpriority59 \lsdlocked0 Table Grid;\lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;
|
||||
\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid;\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;
|
||||
\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2;\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;
|
||||
\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1;\lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;
|
||||
\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;
|
||||
\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;
|
||||
\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;\lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;
|
||||
\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;
|
||||
\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;
|
||||
\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;
|
||||
\lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;
|
||||
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;
|
||||
\lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4;
|
||||
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;
|
||||
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;
|
||||
\lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5;
|
||||
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;
|
||||
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;
|
||||
\lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6;
|
||||
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;
|
||||
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;
|
||||
\lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;
|
||||
\lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4;
|
||||
\lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4;
|
||||
\lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1;
|
||||
\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1;
|
||||
\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2;
|
||||
\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2;
|
||||
\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3;
|
||||
\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4;
|
||||
\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4;
|
||||
\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5;
|
||||
\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5;
|
||||
\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6;
|
||||
\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6;
|
||||
\lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark;
|
||||
\lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1;
|
||||
\lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1;
|
||||
\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2;
|
||||
\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3;
|
||||
\lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3;
|
||||
\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4;
|
||||
\lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4;
|
||||
\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5;
|
||||
\lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5;
|
||||
\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6;
|
||||
\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;}}{\*\datastore 010500000200000018000000
|
||||
4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000
|
||||
d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e500000000000000000000000000ba
|
||||
4262e5f1d101feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000105000000000000}}
|
||||
\pard\nowidctlpar\sb200\cf2\fs18 GenFw.exe -r | -o <OutputFile> [-e <EfiType>] [-c | -t | -l | -u | -b | -z | -s <TimeDate> | -m | -j | --hiipackage | --hiibinpackage | --nonxcompat] [-a] [-p] <InputFile>\par
|
||||
|
||||
\pard\nowidctlpar GenFw.exe \endash h\par
|
||||
GenFw.exe --version\cf0\b0\fs24\par
|
||||
|
||||
\pard\nowidctlpar\sb200\cf2\f1\fs18\par
|
||||
|
||||
\pard\keep\keepn\nowidctlpar\s2\li-1440\sb400\sa60\sl-340\slmult0\cf1\b\f0\fs28 Description\par
|
||||
|
||||
\pard\nowidctlpar\sb200\cf2\b0\fs18 Genfw is mainly used to process PE32 image to get the expected image data or image file. PE32 is a general-purpose image format that contains, among other information, data identifying the target environment for execution of the image. This utility can modify the standard PE32 image to create UEFI image with EFI subsystem type, PI Terse Executable image with the compact TE image header, zero its debug data or reset its time stamp. It can also extract PE32 image data to create bin file, extract PE32 image data section to create Acpi table image, or dump PI TE image header information. It can also parse the text MicroCode definition file to create the MicroCode binary image, merge (concatenate) several MicroCode binary images into a single file by pad value and alignment requirement. This tool also supports the override the input file with the output contents.\par
|
||||
|
||||
\pard\keep\keepn\nowidctlpar\s2\li-1440\sb400\sa60\sl-340\slmult0\cf1\b\fs28 Options\par
|
||||
|
||||
\pard\nowidctlpar\sb200\cf2\b0\fs18 If no options are specified, tool prints usage.\b\par
|
||||
Filename1 [FilenameN]\par
|
||||
|
||||
\pard\nowidctlpar\li360\sb200\b0 Input PE/PE32+ image, or TE image, or MicroCode Txt file, or MicroCode bin file, or hii binary packages.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b -o FileName, --outputfile FileName\par
|
||||
|
||||
\pard\nowidctlpar\li360\sb200\b0 The EFI image, TeImage, AcpiImage, MicroBin, hii package lists file or other modified PE image will be created.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b -e EFI_FILETYPE, --efiImage EFI_FILETYPE\par
|
||||
|
||||
\pard\nowidctlpar\li360\sb200\b0 Create Efi Image. EFI_FILETYPE is one of BASE, SEC, PEI_CORE, PEIM, DXE_CORE, SMM_CORE, DXE_DRIVER, UEFI_APPLICATION, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER, DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER, PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER, APPLICATION, SAL_RT_DRIVER to support all module types.\f1\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b\f0 -c, --acpi\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0 Create Acpi table.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b -t, --terse\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0 Create Te Image.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b -u, --dump\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0 Dump TeImage Header.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b -z, --zero\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0 Zero the Debug Data Fields in the PE input image file. It also zeros the time stamp fields.\f1\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b\f0 -b, --exe2bin\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0 Convert the input EXE to the output BIN file.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b -l, --stripped\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0 Strip off the relocation information data from PE or TE image.\f1\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b\f0 -s timedate, --stamp timedate\par
|
||||
|
||||
\pard\nowidctlpar\li360\sb200\b0 timedate format is \ldblquote yyyy-mm-dd 00:00:00\rdblquote . If timedata is set to \ldblquote NOW\rdblquote , current system time is used. The support date scope is 1970-1-1 8:0:0 ~ 2038-1-19 3:14:07.\f1\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b\f0 -m, --mcifile\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0 Convert input microcode txt definition file to microcode bin file.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b -j, --join\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0 Merge multiple microcode bin files to one file.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b -a NUM, --align NUM\par
|
||||
|
||||
\pard\nowidctlpar\li360\sb200\b0 NUM is one HEX or DEC format alignment value, which is used to combine multiple microcode bin files.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b -p NUM, --pad NUM\par
|
||||
|
||||
\pard\nowidctlpar\li360\sb200\b0 NUM is one HEX or DEC format padding value, which is used to combine multiple microcode bin files.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b --keepexceptiontable\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0 Don\rquote t clear exception table.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b --keepzeropending\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0 Don\rquote t strip zero pending of .reloc.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b -r, --replace\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0 Overwrite the input file with the output content.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0 Guid is used to specify hii package list guid.\f1\par
|
||||
\f0 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b --hiipackage \f1\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0\f0 Combine all input binary hii packages into a single package list as the text resource data file (RC file format).\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b --hiibinpackage \f1\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0\f0 Combine all input binary hii packages into a single package list as the binary resource section.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b --nonxcompat \f1\par
|
||||
\b0\f0 Do not set the IMAGE_DLLCHARACTERISTICS_NX_COMPAT bit of the optional header in the PE header even if the requirements are met.\par
|
||||
\b -v, --verbose\b0\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200 Turn on verbose output with informational messages.\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b -d, --debug level\par
|
||||
\b0\f1\tab\f0 Enable debug message with specified level.\par
|
||||
\b --version\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0 Show program's version number and exit\par
|
||||
|
||||
\pard\nowidctlpar\sb200\b -h, --help\par
|
||||
|
||||
\pard\nowidctlpar\fi360\sb200\b0 Show this help message and exit\par
|
||||
|
||||
\pard\keep\keepn\nowidctlpar\s2\fi-1440\sb400\sa60\sl-340\slmult0\tx1440\cf3\b\fs28 Status codes returned\par
|
||||
\trowd\trgaph10\trleft-118\trbrdrl\brdrs\brdrw10 \trbrdrt\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trpaddl10\trpaddr10\trpaddfl3\trpaddfr3
|
||||
\clbrdrl\brdrw10\brdrs\clbrdrt\brdrw10\brdrs\clbrdrr\brdrw10\brdrs\clbrdrb\brdrw10\brdrs \cellx2852\clbrdrl\brdrw10\brdrs\clbrdrt\brdrw10\brdrs\clbrdrr\brdrw10\brdrs\clbrdrb\brdrw10\brdrs \cellx8702
|
||||
\pard\intbl\widctlpar\ri20\sb60\sa60\sl-200\slmult0\cf4\kerning2\f2\fs18 STATUS_SUCCESS\cf2\kerning0\b0\f0\fs16 \cf4\kerning2\b\f2\fs18\tab 0\cf2\cell\kerning0\b0\f0\fs16 The action was completed as requested.\kerning2\cell\row\trowd\trgaph10\trleft-118\trbrdrl\brdrs\brdrw10 \trbrdrt\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trpaddl10\trpaddr10\trpaddfl3\trpaddfr3
|
||||
\clbrdrl\brdrw10\brdrs\clbrdrt\brdrw10\brdrs\clbrdrr\brdrw10\brdrs\clbrdrb\brdrw10\brdrs \cellx2852\clbrdrl\brdrw10\brdrs\clbrdrt\brdrw10\brdrs\clbrdrr\brdrw10\brdrs\clbrdrb\brdrw10\brdrs \cellx8702
|
||||
\pard\intbl\widctlpar\ri20\sb60\sa60\sl-200\slmult0\cf4\b\f2\fs18 STATUS_ERROR\cf2\kerning0\b0\f0\fs16 \cf4\kerning2\b\f2\fs18\tab\tab 2\cf0\kerning0\b0\f3\fs19\cell\cf2\kerning2\f0\fs16 The action failed.\cell\row
|
||||
\pard\keep\keepn\nowidctlpar\s2\li-1440\sb400\sa60\sl-340\slmult0\cf1\kerning0\b\fs28 Example\par
|
||||
|
||||
\pard\nowidctlpar\sb200\cf2\b0\fs18 1. Generate Efi image with the input PE image, module type and the output file name.\par
|
||||
\b GenFw \endash e PEI_CORE PeiMain.dll \endash o PeiMain.efi\par
|
||||
\b0 2. Generate Te image with the input PE image and the output file name.\par
|
||||
\b GenFw \endash t PeiMain.dll \endash o PeiMain.te\par
|
||||
\b0 3. Generate acpi table image with the input PE image and the output file name.\par
|
||||
\b GenFw \endash c Facs.dll \endash o Facs.acpi\par
|
||||
\b0 4. Dump TeImage Header with the input Te Image and the output file name.\par
|
||||
\b GenFw \endash u PeiMain.te \endash o PeiMain.teheader\par
|
||||
\b0 5. Modify PeImage by zero its debug data.\par
|
||||
\b GenFw \endash z PeiMain.dll \endash o Peimain.zero\par
|
||||
\b0 6. Modify PeImage by set new timestamp and override the input image without the output file name.\par
|
||||
\b GenFw \endash s \ldblquote 2007-8-16 16:06:32\rdblquote PeiMain.dll \endash r\par
|
||||
\b0 7. Extract bin image from PeImage.\par
|
||||
\b GenFw \endash b PeiMain.dll \endash o PeiMain.bin\par
|
||||
\b0 8. Generate the microcode binary file from the micro code txt file.\par
|
||||
\b GenFw \endash m Mci.txt \endash o Mci.bin\par
|
||||
\b0 9. Merge the multiple mci binary files to one file.\par
|
||||
\b GenFw \endash j Mci.bin1 Mci.bin2 Mci.bin3 \endash a 32 \endash p 0xFF \endash o Mci.bin\par
|
||||
\b0 10. Generate the text resource file (RC format) based on all input binary HII packages and their package list guid.\par
|
||||
\b GenFw \endash o SampleHii.rc \endash g D49D2EB0-44D5-4621-9FD6-1A92C9109B99 \endash hiipackage SampleStr.hpk SampleVfr.hpk\f1\par
|
||||
\b0\f0 11. Generate the binary resource section based on all input binary HII packages and their package list guid.\f1\par
|
||||
\b\f0 GenFw \endash o SampleHii.bin \endash g D49D2EB0-44D5-4621-9FD6-1A92C9109B99 \endash hiibinpackage SampleStr.hpk SampleVfr.hpk\f1\par
|
||||
|
||||
\pard\keep\keepn\nowidctlpar\s2\li-1440\sb400\sa60\sl-340\slmult0\cf1\f0\fs28 Bugs\par
|
||||
|
||||
\pard\nowidctlpar\sb200\cf2\b0\fs18 No known bugs.\par
|
||||
Report bugs to \cf5\revised edk2-devel@lists.01.org\cf2\revised0\deleted edk2-buildtools-devel@lists.sourceforge.net\deleted0\f1\par
|
||||
|
||||
\pard\keep\keepn\nowidctlpar\s2\li-1440\sb400\sa60\sl-340\slmult0\cf1\b\f0\fs28 Files\par
|
||||
|
||||
\pard\nowidctlpar\sb200\cf2\b0\fs18 None\par
|
||||
|
||||
\pard\keep\keepn\nowidctlpar\s2\li-1440\sb400\sa60\sl-340\slmult0\cf1\b\fs28 See also\par
|
||||
|
||||
\pard\nowidctlpar\sb200\cf2\b0\fs18 None\par
|
||||
|
||||
\pard\keep\keepn\nowidctlpar\s2\li-1440\sb400\sa60\sl-340\slmult0\cf1\b\fs28 License\par
|
||||
|
||||
\pard\nowidctlpar\cf2\b0\fs18 Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.\par
|
||||
This program and the accompanying materials are licensed and made available \par
|
||||
under the terms and conditions of the BSD License which accompanies this \par
|
||||
distribution. The full text of the license may be found at\par
|
||||
{{\field{\*\fldinst{HYPERLINK http://opensource.org/licenses/bsd-license.php }}{\fldrslt{http://opensource.org/licenses/bsd-license.php\ul0\cf0}}}}\f0\fs18\par
|
||||
\par
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\par
|
||||
|
||||
\pard\nowidctlpar\sb200 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\par
|
||||
\cf0\f1\par
|
||||
}
|
||||
|