diff options
29 files changed, 845 insertions, 1244 deletions
diff --git a/arch/riscv/lib/crt0_riscv_efi.S b/arch/riscv/lib/crt0_riscv_efi.S index e7c4d99..b0a7a39 100644 --- a/arch/riscv/lib/crt0_riscv_efi.S +++ b/arch/riscv/lib/crt0_riscv_efi.S @@ -33,7 +33,10 @@ .globl ImageBase ImageBase: .short IMAGE_DOS_SIGNATURE /* 'MZ' */ - .skip 58 /* 'MZ' + pad + offset == 64 */ + .skip 46 /* 'MZ' + pad + offset == 64 */ + .long 0x43534952 /* Linux magic "RISCV */ + .long 0x00000056 + .long 0x05435352 /* Linux magic2 "RSC\x05*/ .long pe_header - ImageBase /* Offset to the PE header */ pe_header: .long IMAGE_NT_SIGNATURE /* 'PE' */ @@ -72,7 +75,7 @@ extra_header_fields: .long 0x8 /* FileAlignment */ .short 0 /* MajorOperatingSystemVersion */ .short 0 /* MinorOperatingSystemVersion */ - .short 0 /* MajorImageVersion */ + .short 1 /* MajorImageVersion */ .short 0 /* MinorImageVersion */ .short 0 /* MajorSubsystemVersion */ .short 0 /* MinorSubsystemVersion */ diff --git a/doc/README.fdt-control b/doc/README.fdt-control deleted file mode 100644 index 424d13f..0000000 --- a/doc/README.fdt-control +++ /dev/null @@ -1,230 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0+ -# -# Copyright (c) 2011 The Chromium OS Authors. - -Device Tree Control in U-Boot -============================= - -This feature provides for run-time configuration of U-Boot via a flat -device tree (fdt). U-Boot configuration has traditionally been done -using CONFIG options in the board config file. This feature aims to -make it possible for a single U-Boot binary to support multiple boards, -with the exact configuration of each board controlled by a flat device -tree (fdt). This is the approach recently taken by the ARM Linux kernel -and has been used by PowerPC for some time. - -The fdt is a convenient vehicle for implementing run-time configuration -for three reasons. Firstly it is easy to use, being a simple text file. -It is extensible since it consists of nodes and properties in a nice -hierarchical format. - -Finally, there is already excellent infrastructure for the fdt: a -compiler checks the text file and converts it to a compact binary -format, and a library is already available in U-Boot (libfdt) for -handling this format. - -The dts directory contains a Makefile for building the device tree blob -and embedding it in your U-Boot image. This is useful since it allows -U-Boot to configure itself according to what it finds there. If you have -a number of similar boards with different peripherals, you can describe -the features of each board in the device tree file, and have a single -generic source base. - -To enable this feature, add CONFIG_OF_CONTROL to your board config file. - - -What is a Flat Device Tree? ---------------------------- - -An fdt can be specified in source format as a text file. To read about -the fdt syntax, take a look at the specification here: - -https://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf - -You also might find this section of the Linux kernel documentation -useful: (access this in the Linux kernel source code) - - Documentation/devicetree/booting-without-of.txt - -There is also a mailing list: - - http://lists.ozlabs.org/listinfo/devicetree-discuss - -In case you are wondering, OF stands for Open Firmware. - - -Tools ------ - -To use this feature you will need to get the device tree compiler. This is -provided by U-Boot automatically. If you have a system version of dtc -(typically in the 'device-tree-compiler' package), it is currently not used. - -If you want to build your own dtc, it is kept here: - - git://git.kernel.org/pub/scm/utils/dtc/dtc.git - -For example: - - $ git clone git://git.kernel.org/pub/scm/utils/dtc/dtc.git - $ cd dtc - $ make - $ sudo make install - -Then run the compiler (your version will vary): - - $ dtc -v - Version: DTC 1.2.0-g2cb4b51f - $ make tests - $ cd tests - $ ./run_tests.sh - ********** TEST SUMMARY - * Total testcases: 1371 - * PASS: 1371 - * FAIL: 0 - * Bad configuration: 0 - * Strange test result: 0 - -You will also find a useful fdtdump utility for decoding a binary file, as -well as fdtget/fdtput for reading and writing properties in a binary file. - - -Where do I get an fdt file for my board? ----------------------------------------- - -You may find that the Linux kernel has a suitable file. Look in the -kernel source in arch/<arch>/boot/dts. - -If not you might find other boards with suitable files that you can -modify to your needs. Look in the board directories for files with a -.dts extension. - -Failing that, you could write one from scratch yourself! - - -Configuration -------------- - -Use: - -#define CONFIG_DEFAULT_DEVICE_TREE "<name>" - -to set the filename of the device tree source. Then put your device tree -file into - - board/<vendor>/dts/<name>.dts - -This should include your CPU or SOC's device tree file, placed in -arch/<arch>/dts, and then make any adjustments required. - -If CONFIG_OF_EMBED is defined, then it will be picked up and built into -the U-Boot image (including u-boot.bin). This is suitable for debugging -and development only and is not recommended for production devices. - -If CONFIG_OF_SEPARATE is defined, then it will be built and placed in -a u-boot.dtb file alongside u-boot-nodtb.bin. A common approach is then to -join the two: - - cat u-boot-nodtb.bin u-boot.dtb >image.bin - -and then flash image.bin onto your board. Note that U-Boot creates -u-boot-dtb.bin which does the above step for you also. Resulting -u-boot.bin is a copy of u-boot-dtb.bin in this case. If you are using -CONFIG_SPL_FRAMEWORK, then u-boot.img will be built to include the device -tree binary. - -If CONFIG_OF_BOARD is defined, a board-specific routine will provide the -device tree at runtime, for example if an earlier bootloader stage creates -it and passes it to U-Boot. - -If CONFIG_OF_HOSTFILE is defined, then it will be read from a file on -startup. This is only useful for sandbox. Use the -d flag to U-Boot to -specify the file to read. - -You cannot use more than one of these options at the same time. - -To use a device tree file that you have compiled yourself, pass -EXT_DTB=<filename> to 'make', as in: - - make EXT_DTB=boot/am335x-boneblack-pubkey.dtb - -Then U-Boot will copy that file to u-boot.dtb, put it in the .img file -if used, and u-boot-dtb.bin. - -If you wish to put the fdt at a different address in memory, you can -define the "fdtcontroladdr" environment variable. This is the hex -address of the fdt binary blob, and will override either of the options. -Be aware that this environment variable is checked prior to relocation, -when only the compiled-in environment is available. Therefore it is not -possible to define this variable in the saved SPI/NAND flash -environment, for example (it will be ignored). After relocation, this -variable will be set to the address of the newly relocated fdt blob. -It is read-only and cannot be changed. It can optionally be used to -control the boot process of Linux with bootm/bootz commands. - -To use this, put something like this in your board header file: - -#define CONFIG_EXTRA_ENV_SETTINGS "fdtcontroladdr=10000\0" - -Build: - -After board configuration is done, fdt supported u-boot can be build in two ways: -1) build the default dts which is defined from CONFIG_DEFAULT_DEVICE_TREE - $ make -2) build the user specified dts file - $ make DEVICE_TREE=<dts-file-name> - - -Relocation, SPL and TPL ------------------------ - -U-Boot can be divided into three phases: TPL, SPL and U-Boot proper. - -The full device tree is available to U-Boot proper, but normally only a subset -(or none at all) is available to TPL and SPL. See 'Pre-Relocation Support' and -'SPL Support' in doc/driver-model/design.rst for more details. - - -Using several DTBs in the SPL (CONFIG_SPL_MULTI_DTB) ----------------------------------------------------- -In some rare cases it is desirable to let SPL be able to select one DTB among -many. This usually not very useful as the DTB for the SPL is small and usually -fits several platforms. However the DTB sometimes include information that do -work on several platforms (like IO tuning parameters). -In this case it is possible to use CONFIG_SPL_MULTI_DTB. This option appends to -the SPL a FIT image containing several DTBs listed in SPL_OF_LIST. -board_fit_config_name_match() is called to select the right DTB. - -If board_fit_config_name_match() relies on DM (DM driver to access an EEPROM -containing the board ID for example), it possible to start with a generic DTB -and then switch over to the right DTB after the detection. For this purpose, -the platform code must call fdtdec_resetup(). Based on the returned flag, the -platform may have to re-initiliaze the DM subusystem using dm_uninit() and -dm_init_and_scan(). - - -Limitations ------------ - -U-Boot is designed to build with a single architecture type and CPU -type. So for example it is not possible to build a single ARM binary -which runs on your AT91 and OMAP boards, relying on an fdt to configure -the various features. This is because you must select one of -the CPU families within arch/arm/cpu/arm926ejs (omap or at91) at build -time. Similarly you cannot build for multiple cpu types or -architectures. - -That said the complexity reduction by using fdt to support variants of -boards which use the same SOC / CPU can be substantial. - -It is important to understand that the fdt only selects options -available in the platform / drivers. It cannot add new drivers (yet). So -you must still have the CONFIG option to enable the driver. For example, -you need to define CONFIG_SYS_NS16550 to bring in the NS16550 driver, -but can use the fdt to specific the UART clock, peripheral address, etc. -In very broad terms, the CONFIG options in general control *what* driver -files are pulled in, and the fdt controls *how* those files work. - --- -Simon Glass <sjg@chromium.org> -1-Sep-11 diff --git a/doc/board/st/index.rst b/doc/board/st/index.rst index 91f1d51..8a06a95 100644 --- a/doc/board/st/index.rst +++ b/doc/board/st/index.rst @@ -6,4 +6,5 @@ STMicroelectronics .. toctree:: :maxdepth: 2 + st stm32mp1 diff --git a/doc/board/st/st.rst b/doc/board/st/st.rst new file mode 100644 index 0000000..3dade16 --- /dev/null +++ b/doc/board/st/st.rst @@ -0,0 +1,68 @@ +.. SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +.. sectionauthor:: Patrick Delaunay <patrick.delaunay@st.com> + +U-Boot device tree bindings +---------------------------- + +The U-Boot specific bindings are defined in the U-Boot directory: +doc/device-tree-bindings + +* clock + - :download:`clock/st,stm32mp1.txt <../../device-tree-bindings/clock/st,stm32mp1.txt>` +* ram + - :download:`memory-controllers/st,stm32mp1-ddr.txt <../../device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt>` + +All the other device tree bindings used in U-Boot are specified in Linux +kernel. Please refer dt bindings from below specified paths in the Linux +kernel binding directory = Documentation/devicetree/bindings/ + +* acd + - iio/adc/st,stm32-adc.yaml +* clock + - clock/st,stm32-rcc.txt + - clock/st,stm32h7-rcc.txt + - clock/st,stm32mp1-rcc.yaml +* display + - display/st,stm32-dsi.yaml + - display/st,stm32-ltdc.yaml +* gpio + - pinctrl/st,stm32-pinctrl.yaml +* hwlock + - hwlock/st,stm32-hwspinlock.yaml +* i2c + - i2c/st,stm32-i2c.yaml +* mailbox + - mailbox/st,stm32-ipcc.yaml +* mmc + - mmc/arm,pl18x.yaml +* nand + - mtd/st,stm32-fmc2-nand.yaml + - memory-controllers/st,stm32-fmc2-ebi.yaml +* net + - net/stm32-dwmac.yaml +* nvmem + - nvmem/st,stm32-romem.yaml +* remoteproc + - remoteproc/st,stm32-rproc.yaml +* regulator + - regulator/st,stm32mp1-pwr-reg.yaml + - regulator/st,stm32-vrefbuf.yaml +* reset + - reset/st,stm32-rcc.txt + - reset/st,stm32mp1-rcc.txt +* rng + - rng/st,stm32-rng.yaml +* rtc + - rtc/st,stm32-rtc.yaml +* serial + - serial/st,stm32-uart.yaml +* spi + - spi/st,stm32-spi.yaml + - spi/st,stm32-qspi.yaml +* syscon + - arm/stm32/st,stm32-syscon.yaml +* usb + - phy/phy-stm32-usbphyc.yaml + - usb/dwc2.yaml +* watchdog + - watchdog/st,stm32-iwdg.yaml diff --git a/doc/build/gcc.rst b/doc/build/gcc.rst index e03e0b9..0cdc307 100644 --- a/doc/build/gcc.rst +++ b/doc/build/gcc.rst @@ -26,8 +26,8 @@ Depending on the build targets further packages maybe needed sudo apt-get install bc bison build-essential coccinelle \ device-tree-compiler dfu-util efitools flex gdisk graphviz imagemagick \ liblz4-tool libguestfs-tools libncurses-dev libpython3-dev libsdl2-dev \ - libssl-dev lz4 lzma lzma-alone openssl python3 python3-coverage \ - python3-pycryptodome python3-pyelftools python3-pytest \ + libssl-dev lz4 lzma lzma-alone openssl pkg-config python3 \ + python3-coverage python3-pycryptodome python3-pyelftools python3-pytest \ python3-sphinxcontrib.apidoc python3-sphinx-rtd-theme python3-virtualenv \ swig diff --git a/doc/conf.py b/doc/conf.py index eb74b86..eac3acc 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -31,7 +31,7 @@ from load_config import loadConfig # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = '1.3' +needs_sphinx = '2.4.4' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom @@ -118,19 +118,12 @@ if major >= 3: else: extensions.append('cdomain') - if major == 1 and minor < 7: - sys.stderr.write('WARNING: Sphinx 1.7 or greater will be required as of ' - 'the v2021.04 release\n') # Ensure that autosectionlabel will produce unique names autosectionlabel_prefix_document = True autosectionlabel_maxdepth = 2 -# The name of the math extension changed on Sphinx 1.4 -if (major == 1 and minor > 3) or (major > 1): - extensions.append("sphinx.ext.imgmath") -else: - extensions.append("sphinx.ext.pngmath") +extensions.append("sphinx.ext.imgmath") # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -345,27 +338,34 @@ htmlhelp_basename = 'TheUBootdoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -'papersize': 'a4paper', + # The paper size ('letterpaper' or 'a4paper'). + 'papersize': 'a4paper', + + # The font size ('10pt', '11pt' or '12pt'). + 'pointsize': '11pt', -# The font size ('10pt', '11pt' or '12pt'). -'pointsize': '11pt', + # Latex figure (float) alignment + #'figure_align': 'htbp', -# Latex figure (float) alignment -#'figure_align': 'htbp', + # Don't mangle with UTF-8 chars + 'inputenc': '', + 'utf8extra': '', -# Don't mangle with UTF-8 chars -'inputenc': '', -'utf8extra': '', + # Set document margins + 'sphinxsetup': ''' + hmargin=0.5in, vmargin=1in, + parsedliteralwraps=true, + verbatimhintsturnover=false, + ''', -# Additional stuff for the LaTeX preamble. + # Additional stuff for the LaTeX preamble. 'preamble': ''' - % Use some font with UTF-8 support with XeLaTeX + % Use some font with UTF-8 support with XeLaTeX \\usepackage{fontspec} \\setsansfont{DejaVu Sans} \\setromanfont{DejaVu Serif} \\setmonofont{DejaVu Sans Mono} - ''' + ''', } # At least one book (translations) may have Asian characters @@ -380,72 +380,6 @@ if cjk_cmd.find("Noto Sans CJK SC") >= 0: \\setCJKmainfont{Noto Sans CJK SC} ''' -# Fix reference escape troubles with Sphinx 1.4.x -if major == 1 and minor > 3: - latex_elements['preamble'] += '\\renewcommand*{\\DUrole}[2]{ #2 }\n' - -if major == 1 and minor <= 4: - latex_elements['preamble'] += '\\usepackage[margin=0.5in, top=1in, bottom=1in]{geometry}' -elif major == 1 and (minor > 5 or (minor == 5 and patch >= 3)): - latex_elements['sphinxsetup'] = 'hmargin=0.5in, vmargin=1in' - latex_elements['preamble'] += '\\fvset{fontsize=auto}\n' - -# Customize notice background colors on Sphinx < 1.6: -if major == 1 and minor < 6: - latex_elements['preamble'] += ''' - \\usepackage{ifthen} - - % Put notes in color and let them be inside a table - \\definecolor{NoteColor}{RGB}{204,255,255} - \\definecolor{WarningColor}{RGB}{255,204,204} - \\definecolor{AttentionColor}{RGB}{255,255,204} - \\definecolor{ImportantColor}{RGB}{192,255,204} - \\definecolor{OtherColor}{RGB}{204,204,204} - \\newlength{\\mynoticelength} - \\makeatletter\\newenvironment{coloredbox}[1]{% - \\setlength{\\fboxrule}{1pt} - \\setlength{\\fboxsep}{7pt} - \\setlength{\\mynoticelength}{\\linewidth} - \\addtolength{\\mynoticelength}{-2\\fboxsep} - \\addtolength{\\mynoticelength}{-2\\fboxrule} - \\begin{lrbox}{\\@tempboxa}\\begin{minipage}{\\mynoticelength}}{\\end{minipage}\\end{lrbox}% - \\ifthenelse% - {\\equal{\\py@noticetype}{note}}% - {\\colorbox{NoteColor}{\\usebox{\\@tempboxa}}}% - {% - \\ifthenelse% - {\\equal{\\py@noticetype}{warning}}% - {\\colorbox{WarningColor}{\\usebox{\\@tempboxa}}}% - {% - \\ifthenelse% - {\\equal{\\py@noticetype}{attention}}% - {\\colorbox{AttentionColor}{\\usebox{\\@tempboxa}}}% - {% - \\ifthenelse% - {\\equal{\\py@noticetype}{important}}% - {\\colorbox{ImportantColor}{\\usebox{\\@tempboxa}}}% - {\\colorbox{OtherColor}{\\usebox{\\@tempboxa}}}% - }% - }% - }% - }\\makeatother - - \\makeatletter - \\renewenvironment{notice}[2]{% - \\def\\py@noticetype{#1} - \\begin{coloredbox}{#1} - \\bf\\it - \\par\\strong{#2} - \\csname py@noticestart@#1\\endcsname - } - { - \\csname py@noticeend@\\py@noticetype\\endcsname - \\end{coloredbox} - } - \\makeatother - - ''' - # With Sphinx 1.6, it is possible to change the Bg color directly # by using: # \definecolor{sphinxnoteBgColor}{RGB}{204,255,255} diff --git a/doc/develop/devicetree/control.rst b/doc/develop/devicetree/control.rst new file mode 100644 index 0000000..e84dfb6 --- /dev/null +++ b/doc/develop/devicetree/control.rst @@ -0,0 +1,251 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. sectionauthor:: Copyright 2011 The Chromium OS Authors + +Devicetree Control in U-Boot +============================ + +This feature provides for run-time configuration of U-Boot via a flattened +devicetree (fdt). + +This feature aims to make it possible for a single U-Boot binary to support +multiple boards, with the exact configuration of each board controlled by +a flattened devicetree (fdt). This is the approach taken by Linux kernel for +ARM and RISC-V and has been used by PowerPC for some time. + +The fdt is a convenient vehicle for implementing run-time configuration +for three reasons: + +- There is already excellent infrastructure for the fdt: a compiler checks + the text file and converts it to a compact binary format, and a library + is already available in U-Boot (libfdt) for handling this format +- It is extensible since it consists of nodes and properties in a nice + hierarchical format +- It is fairly efficient to read incrementally + +The arch/<arch>/dts directories contains a Makefile for building the devicetree +blob and embedding it in the U-Boot image. This is useful since it allows +U-Boot to configure itself according to what it finds there. If you have +a number of similar boards with different peripherals, you can describe +the features of each board in the devicetree file, and have a single +generic source base. + +To enable this feature, add CONFIG_OF_CONTROL to your board config file. + + +What is a Flattened Devicetree? +------------------------------- + +An fdt can be specified in source format as a text file. To read about +the fdt syntax, take a look at the specification (dtspec_). + +There is also a mailing list (dtlist_) for the compiler and associated +tools. + +In case you are wondering, OF stands for Open Firmware. This follows the +convention used in Linux. + + +Tools +----- + +To create flattened device trees the device tree compiler is used. This is +provided by U-Boot automatically. If you have a system version of dtc +(typically in the 'device-tree-compiler' package), that system version is +currently not used. + +If you want to build your own dtc, it is kept here:: + + git://git.kernel.org/pub/scm/utils/dtc/dtc.git + +You can decode a binary file with:: + + dtc -I dtb -O dts <filename.dtb> + +That repo also includes `fdtget`/`fdtput` for reading and writing properties in +a binary file. U-Boot adds its own `fdtgrep` for creating subsets of the file. + + +Where do I get a devicetree file for my board? +---------------------------------------------- + +You may find that the Linux kernel has a suitable file. Look in the +kernel source in arch/<arch>/boot/dts. + +If not you might find other boards with suitable files that you can +modify to your needs. Look in the board directories for files with a +.dts extension. + +Failing that, you could write one from scratch yourself! + + +Configuration +------------- + +Use:: + + #define CONFIG_DEFAULT_DEVICE_TREE "<name>" + +to set the filename of the devicetree source. Then put your devicetree +file into:: + + arch/<arch>/dts/<name>.dts + +This should include your CPU or SOC's devicetree file, placed in +`arch/<arch>/dts`, and then make any adjustments required using a u-boot-dtsi +file for your board. + +If CONFIG_OF_EMBED is defined, then it will be picked up and built into +the U-Boot image (including u-boot.bin). This is suitable for debugging +and development only and is not recommended for production devices. + +If CONFIG_OF_SEPARATE is defined, then it will be built and placed in +a u-boot.dtb file alongside u-boot-nodtb.bin with the combined result placed +in u-boot.bin so you can still just flash u-boot,bin onto your board. If you are +using CONFIG_SPL_FRAMEWORK, then u-boot.img will be built to include the device +tree binary. + +If CONFIG_OF_BOARD is defined, a board-specific routine will provide the +devicetree at runtime, for example if an earlier bootloader stage creates +it and passes it to U-Boot. + +If CONFIG_OF_HOSTFILE is defined, then it will be read from a file on +startup. This is only useful for sandbox. Use the -d flag to U-Boot to +specify the file to read, -D for the default and -T for the test devicetree, +used to run sandbox unit tests. + +You cannot use more than one of these options at the same time. + +To use a devicetree file that you have compiled yourself, pass +EXT_DTB=<filename> to 'make', as in:: + + make EXT_DTB=boot/am335x-boneblack-pubkey.dtb + +Then U-Boot will copy that file to u-boot.dtb, put it in the .img file +if used, and u-boot-dtb.bin. + +If you wish to put the fdt at a different address in memory, you can +define the "fdtcontroladdr" environment variable. This is the hex +address of the fdt binary blob, and will override either of the options. +Be aware that this environment variable is checked prior to relocation, +when only the compiled-in environment is available. Therefore it is not +possible to define this variable in the saved SPI/NAND flash +environment, for example (it will be ignored). After relocation, this +variable will be set to the address of the newly relocated fdt blob. +It is read-only and cannot be changed. It can optionally be used to +control the boot process of Linux with bootm/bootz commands. + +To use this, put something like this in your board header file:: + + #define CONFIG_EXTRA_ENV_SETTINGS "fdtcontroladdr=10000\0" + +Build: + +After the board configuration is done, fdt supported u-boot can be built in two +ways: + +# build the default dts which is defined from CONFIG_DEFAULT_DEVICE_TREE:: + + $ make + +# build the user specified dts file:: + + $ make DEVICE_TREE=<dts-file-name> + + +.. _dttweaks: + +Adding tweaks for U-Boot +------------------------ + +It is strongly recommended that devicetree files in U-Boot are an exact copy of +those in Linux, so that it is easy to sync them up from time to time. + +U-Boot is of course a very different project from Linux, e.g. it operates under +much more restrictive memory and code-size constraints. Where Linux may use a +full clock driver with Common Clock Format (CCF) to find the input clock to the +UART, U-Boot typically wants to output a banner as early as possible before too +much code has run. + +A second difference is that U-Boot includes different phases. For SPL, +constraints are even more extreme and the devicetree is shrunk to remove +unwanted nodes, or even turned into C code to avoid access overhead. + +U-Boot automatically looks for and includes a file with updates to the standard +devicetree for your board, searching for them in the same directory as the +main file, in this order:: + + <orig_filename>-u-boot.dtsi + <CONFIG_SYS_SOC>-u-boot.dtsi + <CONFIG_SYS_CPU>-u-boot.dtsi + <CONFIG_SYS_VENDOR>-u-boot.dtsi + u-boot.dtsi + +Only one of these is selected but of course you can #include another one within +that file, to create a hierarchy of shared files. + +Relocation, SPL and TPL +----------------------- + +U-Boot can be divided into three phases: TPL, SPL and U-Boot proper. + +The full devicetree is available to U-Boot proper, but normally only a subset +(or none at all) is available to TPL and SPL. See 'Pre-Relocation Support' and +'SPL Support' in doc/driver-model/design.rst for more details. + + +Using several DTBs in the SPL (CONFIG_SPL_MULTI_DTB) +---------------------------------------------------- +In some rare cases it is desirable to let SPL be able to select one DTB among +many. This usually not very useful as the DTB for the SPL is small and usually +fits several platforms. However the DTB sometimes include information that do +work on several platforms (like IO tuning parameters). +In this case it is possible to use CONFIG_SPL_MULTI_DTB. This option appends to +the SPL a FIT image containing several DTBs listed in SPL_OF_LIST. +board_fit_config_name_match() is called to select the right DTB. + +If board_fit_config_name_match() relies on DM (DM driver to access an EEPROM +containing the board ID for example), it possible to start with a generic DTB +and then switch over to the right DTB after the detection. For this purpose, +the platform code must call fdtdec_resetup(). Based on the returned flag, the +platform may have to re-initialise the DM subsystem using dm_uninit() and +dm_init_and_scan(). + + +Limitations +----------- + +Devicetrees can help reduce the complexity of supporting variants of boards +which use the same SOC / CPU. + +However U-Boot is designed to build for a single architecture type and CPU +type. So for example it is not possible to build a single ARM binary +which runs on your AT91 and OMAP boards, relying on an fdt to configure +the various features. This is because you must select one of +the CPU families within arch/arm/cpu/arm926ejs (omap or at91) at build +time. Similarly U-Boot cannot be built for multiple cpu types or +architectures. + +It is important to understand that the fdt only selects options +available in the platform / drivers. It cannot add new drivers (yet). So +you must still have the CONFIG option to enable the driver. For example, +you need to define CONFIG_SYS_NS16550 to bring in the NS16550 driver, +but can use the fdt to specific the UART clock, peripheral address, etc. +In very broad terms, the CONFIG options in general control *what* driver +files are pulled in, and the fdt controls *how* those files work. + +History +------- + +U-Boot configuration was previous done using CONFIG options in the board +config file. This eventually got out of hand with nearly 10,000 options. + +U-Boot adopted devicetrees around the same time as Linux and early boards +used it before Linux (e.g. snow). The two projects developed in parallel +and there are still some differences in the bindings for certain boards. +While there has been discussion of having a separate repository for devicetree +files, in practice the Linux kernel Git repository has become the place where +these are stored, with U-Boot taking copies and adding tweaks with u-boot.dtsi +files. + +.. _dtspec: https://www.devicetree.org/specifications/ +.. _dtlist: https://www.spinics.net/lists/devicetree-compiler/ diff --git a/doc/develop/devicetree/index.rst b/doc/develop/devicetree/index.rst new file mode 100644 index 0000000..fa5db3e --- /dev/null +++ b/doc/develop/devicetree/index.rst @@ -0,0 +1,13 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Devicetree in U-Boot +==================== + +The following holds information on how U-Boot makes use of devicetree for +build-time and runtime configuration. + +.. toctree:: + :maxdepth: 2 + + intro + control diff --git a/doc/develop/devicetree/intro.rst b/doc/develop/devicetree/intro.rst new file mode 100644 index 0000000..36e8cc0 --- /dev/null +++ b/doc/develop/devicetree/intro.rst @@ -0,0 +1,44 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Devicetree Introduction +======================= + +U-Boot uses a devicetree for configuration. This includes the devices used by +the board, the format of the image created with binman, which UART to use for +the console, public keys used for secure boot and many other things. + +See :doc:`control` for more information. + +Why does U-Boot put <thing> in the devicetree? +---------------------------------------------- + +This question comes up a lot with people new to U-Boot, particular those coming +from Linux who are used to quite strict rules about what can go into the +devicetree. + +U-Boot uses the same devicetree as Linux but adds more things necessary for the +bootloader environment (see :ref:`dttweaks`). + +U-Boot does not have a user space to provide policy and configuration. It cannot +do what Linux does and run programs and look up filesystems to figure out how to +boot. So configuration and runtime information goes into the devicetree in +U-Boot. + +Of course it is possible to: + +- add tables into the rodata section of the U-Boot binary +- append some info to the end of U-Boot in a different format +- modify the linker script to bring in a file with some info in it +- put things in ACPI tables +- link in a UEFI hand-off block structure and put things in there + +but *please don't*. In general, devicetree is the sane place to hold U-Boot's +configuration. + +So, please, do NOT ask why U-Boot puts <thing> in the devicetree. It is the only +place it can go. It is a highly suitable data structure for just about anything +that U-Boot needs to know at runtime. + +Note, it is possible to use platdata directly so drivers avoid devicetreee in +SPL. But of-platdata is the modern way of avoiding devicetree overhead, so +please use that instead. diff --git a/doc/develop/index.rst b/doc/develop/index.rst index 1203409..83c929b 100644 --- a/doc/develop/index.rst +++ b/doc/develop/index.rst @@ -11,6 +11,7 @@ Implementation ci_testing commands + devicetree/index driver-model/index global_data logging diff --git a/doc/device-tree-bindings/adc/st,stm32-adc.txt b/doc/device-tree-bindings/adc/st,stm32-adc.txt deleted file mode 100644 index 07fb6cd..0000000 --- a/doc/device-tree-bindings/adc/st,stm32-adc.txt +++ /dev/null @@ -1,141 +0,0 @@ -STMicroelectronics STM32 ADC device - -STM32 ADC is a successive approximation analog-to-digital converter. -It has several multiplexed input channels. Conversions can be performed -in single, continuous, scan or discontinuous mode. Result of the ADC is -stored in a left-aligned or right-aligned 32-bit data register. -Conversions can be launched in software or using hardware triggers. - -The analog watchdog feature allows the application to detect if the input -voltage goes beyond the user-defined, higher or lower thresholds. - -Each STM32 ADC block can have up to 3 ADC instances. - -Each instance supports two contexts to manage conversions, each one has its -own configurable sequence and trigger: -- regular conversion can be done in sequence, running in background -- injected conversions have higher priority, and so have the ability to - interrupt regular conversion sequence (either triggered in SW or HW). - Regular sequence is resumed, in case it has been interrupted. - -Contents of a stm32 adc root node: ------------------------------------ -Required properties: -- compatible: Should be one of: - "st,stm32f4-adc-core" - "st,stm32h7-adc-core" - "st,stm32mp1-adc-core" -- reg: Offset and length of the ADC block register set. -- interrupts: One or more interrupts for ADC block. Some parts like stm32f4 - and stm32h7 share a common ADC interrupt line. stm32mp1 has two separate - interrupt lines, one for each ADC within ADC block. -- clocks: Core can use up to two clocks, depending on part used: - - "adc" clock: for the analog circuitry, common to all ADCs. - It's required on stm32f4. - It's optional on stm32h7. - - "bus" clock: for registers access, common to all ADCs. - It's not present on stm32f4. - It's required on stm32h7. -- clock-names: Must be "adc" and/or "bus" depending on part used. -- interrupt-controller: Identifies the controller node as interrupt-parent -- vref-supply: Phandle to the vref input analog reference voltage. -- #interrupt-cells = <1>; -- #address-cells = <1>; -- #size-cells = <0>; - -Optional properties: -- A pinctrl state named "default" for each ADC channel may be defined to set - inX ADC pins in mode of operation for analog input on external pin. - -Contents of a stm32 adc child node: ------------------------------------ -An ADC block node should contain at least one subnode, representing an -ADC instance available on the machine. - -Required properties: -- compatible: Should be one of: - "st,stm32f4-adc" - "st,stm32h7-adc" - "st,stm32mp1-adc" -- reg: Offset of ADC instance in ADC block (e.g. may be 0x0, 0x100, 0x200). -- clocks: Input clock private to this ADC instance. It's required only on - stm32f4, that has per instance clock input for registers access. -- interrupt-parent: Phandle to the parent interrupt controller. -- interrupts: IRQ Line for the ADC (e.g. may be 0 for adc@0, 1 for adc@100 or - 2 for adc@200). -- st,adc-channels: List of single-ended channels muxed for this ADC. - It can have up to 16 channels on stm32f4 or 20 channels on stm32h7, numbered - from 0 to 15 or 19 (resp. for in0..in15 or in0..in19). -- st,adc-diff-channels: List of differential channels muxed for this ADC. - Depending on part used, some channels can be configured as differential - instead of single-ended (e.g. stm32h7). List here positive and negative - inputs pairs as <vinp vinn>, <vinp vinn>,... vinp and vinn are numbered - from 0 to 19 on stm32h7) - Note: At least one of "st,adc-channels" or "st,adc-diff-channels" is required. - Both properties can be used together. Some channels can be used as - single-ended and some other ones as differential (mixed). But channels - can't be configured both as single-ended and differential (invalid). -- #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in - Documentation/devicetree/bindings/iio/iio-bindings.txt - -Optional properties: -- dmas: Phandle to dma channel for this ADC instance. - See ../../dma/dma.txt for details. -- dma-names: Must be "rx" when dmas property is being used. -- assigned-resolution-bits: Resolution (bits) to use for conversions. Must - match device available resolutions: - * can be 6, 8, 10 or 12 on stm32f4 - * can be 8, 10, 12, 14 or 16 on stm32h7 - Default is maximum resolution if unset. -- st,min-sample-time-nsecs: Minimum sampling time in nanoseconds. - Depending on hardware (board) e.g. high/low analog input source impedance, - fine tune of ADC sampling time may be recommended. - This can be either one value or an array that matches 'st,adc-channels' list, - to set sample time resp. for all channels, or independently for each channel. - -Example: - adc: adc@40012000 { - compatible = "st,stm32f4-adc-core"; - reg = <0x40012000 0x400>; - interrupts = <18>; - clocks = <&rcc 0 168>; - clock-names = "adc"; - vref-supply = <®_vref>; - interrupt-controller; - pinctrl-names = "default"; - pinctrl-0 = <&adc3_in8_pin>; - - #interrupt-cells = <1>; - #address-cells = <1>; - #size-cells = <0>; - - adc@0 { - compatible = "st,stm32f4-adc"; - #io-channel-cells = <1>; - reg = <0x0>; - clocks = <&rcc 0 168>; - interrupt-parent = <&adc>; - interrupts = <0>; - st,adc-channels = <8>; - dmas = <&dma2 0 0 0x400 0x0>; - dma-names = "rx"; - assigned-resolution-bits = <8>; - }; - ... - other adc child nodes follow... - }; - -Example to setup: -- channel 1 as single-ended -- channels 2 & 3 as differential (with resp. 6 & 7 negative inputs) - - adc: adc@40022000 { - compatible = "st,stm32h7-adc-core"; - ... - adc1: adc@0 { - compatible = "st,stm32h7-adc"; - ... - st,adc-channels = <1>; - st,adc-diff-channels = <2 6>, <3 7>; - }; - }; diff --git a/doc/device-tree-bindings/clock/st,stm32-rcc.txt b/doc/device-tree-bindings/clock/st,stm32-rcc.txt deleted file mode 100644 index 0532d81..0000000 --- a/doc/device-tree-bindings/clock/st,stm32-rcc.txt +++ /dev/null @@ -1,95 +0,0 @@ -STMicroelectronics STM32 Reset and Clock Controller -=================================================== - -The RCC IP is both a reset and a clock controller. - -Please refer to clock-bindings.txt for common clock controller binding usage. -Please also refer to reset.txt for common reset controller binding usage. - -Required properties: -- compatible: Should be: - "st,stm32f42xx-rcc" - "st,stm32f469-rcc" -- reg: should be register base and length as documented in the - datasheet -- #reset-cells: 1, see below -- #clock-cells: 2, device nodes should specify the clock in their "clocks" - property, containing a phandle to the clock device node, an index selecting - between gated clocks and other clocks and an index specifying the clock to - use. - -Example: - - rcc: rcc@40023800 { - #reset-cells = <1>; - #clock-cells = <2> - compatible = "st,stm32f42xx-rcc", "st,stm32-rcc"; - reg = <0x40023800 0x400>; - }; - -Specifying gated clocks -======================= - -The primary index must be set to 0. - -The secondary index is the bit number within the RCC register bank, starting -from the first RCC clock enable register (RCC_AHB1ENR, address offset 0x30). - -It is calculated as: index = register_offset / 4 * 32 + bit_offset. -Where bit_offset is the bit offset within the register (LSB is 0, MSB is 31). - -To simplify the usage and to share bit definition with the reset and clock -drivers of the RCC IP, macros are available to generate the index in -human-readble format. - -For STM32F4 series, the macro are available here: - - include/dt-bindings/mfd/stm32f4-rcc.h - -Example: - - /* Gated clock, AHB1 bit 0 (GPIOA) */ - ... { - clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOA)> - }; - - /* Gated clock, AHB2 bit 4 (CRYP) */ - ... { - clocks = <&rcc 0 STM32F4_AHB2_CLOCK(CRYP)> - }; - -Specifying other clocks -======================= - -The primary index must be set to 1. - -The secondary index is bound with the following magic numbers: - - 0 SYSTICK - 1 FCLK - -Example: - - /* Misc clock, FCLK */ - ... { - clocks = <&rcc 1 STM32F4_APB1_CLOCK(TIM2)> - }; - - -Specifying softreset control of devices -======================================= - -Device nodes should specify the reset channel required in their "resets" -property, containing a phandle to the reset device node and an index specifying -which channel to use. -The index is the bit number within the RCC registers bank, starting from RCC -base address. -It is calculated as: index = register_offset / 4 * 32 + bit_offset. -Where bit_offset is the bit offset within the register. -For example, for CRC reset: - crc = AHB1RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x10 / 4 * 32 + 12 = 140 - -example: - - timer2 { - resets = <&rcc STM32F4_APB1_RESET(TIM2)>; - }; diff --git a/doc/device-tree-bindings/clock/st,stm32h7-rcc.txt b/doc/device-tree-bindings/clock/st,stm32h7-rcc.txt deleted file mode 100644 index 9d4b587..0000000 --- a/doc/device-tree-bindings/clock/st,stm32h7-rcc.txt +++ /dev/null @@ -1,152 +0,0 @@ -STMicroelectronics STM32H7 Reset and Clock Controller -===================================================== - -The RCC IP is both a reset and a clock controller. - -Please refer to clock-bindings.txt for common clock controller binding usage. -Please also refer to reset.txt for common reset controller binding usage. - -Required properties: -- compatible: Should be: - "st,stm32h743-rcc" - -- reg: should be register base and length as documented in the - datasheet - -- #reset-cells: 1, see below - -- #clock-cells : from common clock binding; shall be set to 1 - -- clocks: External oscillator clock phandle - - high speed external clock signal (HSE) - - low speed external clock signal (LSE) - - external I2S clock (I2S_CKIN) - -- st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain - write protection (RTC clock). - -- pll x node: Allow to register a pll with specific parameters. - Please see PLL section below. - -Example: - - rcc: rcc@58024400 { - #reset-cells = <1>; - #clock-cells = <2> - compatible = "st,stm32h743-rcc", "st,stm32-rcc"; - reg = <0x58024400 0x400>; - clocks = <&clk_hse>, <&clk_lse>, <&clk_i2s_ckin>; - - st,syscfg = <&pwrcfg>; - - #address-cells = <1>; - #size-cells = <0>; - - vco1@58024430 { - #clock-cells = <0>; - compatible = "stm32,pll"; - reg = <0>; - }; - - vco2@58024438 { - #clock-cells = <0>; - compatible = "stm32,pll"; - reg = <1>; - st,clock-div = <2>; - st,clock-mult = <40>; - st,frac-status = <0>; - st,frac = <0>; - st,vcosel = <1>; - st,pllrge = <2>; - }; - }; - - -STM32H7 PLL ------------ - -The VCO of STM32 PLL could be reprensented like this: - - Vref --------- -------- - ---->| / DIVM |---->| x DIVN | ------> VCO - --------- -------- - ^ - | - ------- - | FRACN | - ------- - -When the PLL is configured in integer mode: -- VCO = ( Vref / DIVM ) * DIVN - -When the PLL is configured in fractional mode: -- VCO = ( Vref / DIVM ) * ( DIVN + FRACN / 2^13) - - -Required properties for pll node: -- compatible: Should be: - "stm32,pll" - -- #clock-cells: from common clock binding; shall be set to 0 -- reg: Should be the pll number. - -Optional properties: -- st,clock-div: DIVM division factor : <1..63> -- st,clock-mult: DIVN multiplication factor : <4..512> - -- st,frac-status: - - 0 Pll is configured in integer mode - - 1 Pll is configure in fractional mode - -- st,frac: Fractional part of the multiplication factor : <0..8191> - -- st,vcosel: VCO selection - - 0: Wide VCO range:192 to 836 MHz - - 1: Medium VCO range:150 to 420 MHz - -- st,pllrge: PLL input frequency range - - 0: The PLL input (Vref / DIVM) clock range frequency is between 1 and 2 MHz - - 1: The PLL input (Vref / DIVM) clock range frequency is between 2 and 4 MHz - - 2: The PLL input (Vref / DIVM) clock range frequency is between 4 and 8 MHz - - 3: The PLL input (Vref / DIVM) clock range frequency is between 8 and 16 MHz - - -The peripheral clock consumer should specify the desired clock by -having the clock ID in its "clocks" phandle cell. - -All available clocks are defined as preprocessor macros in -dt-bindings/clock/stm32h7-clks.h header and can be used in device -tree sources. - -Example: - - timer5: timer@40000c00 { - compatible = "st,stm32-timer"; - reg = <0x40000c00 0x400>; - interrupts = <50>; - clocks = <&rcc TIM5_CK>; - - }; - -Specifying softreset control of devices -======================================= - -Device nodes should specify the reset channel required in their "resets" -property, containing a phandle to the reset device node and an index specifying -which channel to use. -The index is the bit number within the RCC registers bank, starting from RCC -base address. -It is calculated as: index = register_offset / 4 * 32 + bit_offset. -Where bit_offset is the bit offset within the register. - -For example, for CRC reset: - crc = AHB4RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x88 / 4 * 32 + 19 = 1107 - -All available preprocessor macros for reset are defined dt-bindings//mfd/stm32h7-rcc.h -header and can be used in device tree sources. - -example: - - timer2 { - resets = <&rcc STM32H7_APB1L_RESET(TIM2)>; - }; diff --git a/doc/device-tree-bindings/i2c/i2c-stm32.txt b/doc/device-tree-bindings/i2c/i2c-stm32.txt deleted file mode 100644 index df03743..0000000 --- a/doc/device-tree-bindings/i2c/i2c-stm32.txt +++ /dev/null @@ -1,30 +0,0 @@ -* I2C controller embedded in STMicroelectronis STM32 platforms - -Required properties : -- compatible : Must be "st,stm32f7-i2c" -- reg : Offset and length of the register set for the device -- resets: Must contain the phandle to the reset controller -- clocks: Must contain the input clock of the I2C instance -- A pinctrl state named "default" must be defined to set pins in mode of - operation for I2C transfer -- #address-cells = <1>; -- #size-cells = <0>; - -Optional properties : -- clock-frequency : Desired I2C bus clock frequency in Hz. If not specified, - the default 100 kHz frequency will be used. As only Normal, Fast and Fast+ - modes are implemented, possible values are 100000, 400000 and 1000000. - -Example : - - i2c1: i2c@40005400 { - compatible = "st,stm32f7-i2c"; - reg = <0x40005400 0x400>; - resets = <&rcc 181>; - clocks = <&clk_pclk1>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_i2c1>; - clock-frequency = <400000>; - #address-cells = <1>; - #size-cells = <0>; - }; diff --git a/doc/device-tree-bindings/memory-controllers/st,stm32-fmc.txt b/doc/device-tree-bindings/memory-controllers/st,stm32-fmc.txt deleted file mode 100644 index 99f76d5..0000000 --- a/doc/device-tree-bindings/memory-controllers/st,stm32-fmc.txt +++ /dev/null @@ -1,58 +0,0 @@ -ST, stm32 flexible memory controller Drive -Required properties: -- compatible : "st,stm32-fmc" -- reg : fmc controller base address -- clocks : fmc controller clock -u-boot,dm-pre-reloc: flag to initialize memory before relocation. - -on-board sdram memory attributes: -- st,sdram-control : parameters for sdram configuration, in this order: - number of columns - number of rows - memory width - number of intenal banks in memory - cas latency - read burst enable or disable - read pipe delay - -- st,sdram-timing: timings for sdram, in this order: - tmrd - txsr - tras - trc - trp - trcd - -There is device tree include file at : -include/dt-bindings/memory/stm32-sdram.h to define sdram control and timing -parameters as MACROS. - -Example: - fmc: fmc@A0000000 { - compatible = "st,stm32-fmc"; - reg = <0xA0000000 0x1000>; - clocks = <&rcc 0 64>; - u-boot,dm-pre-reloc; - }; - - &fmc { - pinctrl-0 = <&fmc_pins>; - pinctrl-names = "default"; - status = "okay"; - - /* sdram memory configuration from sdram datasheet */ - bank1: bank@0 { - st,sdram-control = /bits/ 8 <NO_COL_8 NO_ROW_12 MWIDTH_16 BANKS_2 - CAS_3 RD_BURST_EN RD_PIPE_DL_0>; - st,sdram-timing = /bits/ 8 <TMRD_1 TXSR_60 TRAS_42 TRC_60 TRP_18 - TRCD_18>; - }; - - /* sdram memory configuration from sdram datasheet */ - bank2: bank@1 { - st,sdram-control = /bits/ 8 <NO_COL_8 NO_ROW_12 MWIDTH_16 BANKS_2 - CAS_3 RD_BURST_EN RD_PIPE_DL_0>; - st,sdram-timing = /bits/ 8 <TMRD_1 TXSR_60 TRAS_42 TRC_60 TRP_18 - TRCD_18>; - }; - } diff --git a/doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt b/doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt deleted file mode 100644 index ad2bef8..0000000 --- a/doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt +++ /dev/null @@ -1,61 +0,0 @@ -STMicroelectronics Flexible Memory Controller 2 (FMC2) -NAND Interface - -Required properties: -- compatible: Should be one of: - * st,stm32mp15-fmc2 -- reg: NAND flash controller memory areas. - First region contains the register location. - Regions 2 to 4 respectively contain the data, command, - and address space for CS0. - Regions 5 to 7 contain the same areas for CS1. -- interrupts: The interrupt number -- pinctrl-0: Standard Pinctrl phandle (see: pinctrl/pinctrl-bindings.txt) -- clocks: The clock needed by the NAND flash controller - -Optional properties: -- resets: Reference to a reset controller asserting the FMC controller -- dmas: DMA specifiers (see: dma/stm32-mdma.txt) -- dma-names: Must be "tx", "rx" and "ecc" - -* NAND device bindings: - -Required properties: -- reg: describes the CS lines assigned to the NAND device. - -Optional properties: -- nand-on-flash-bbt: see nand.txt -- nand-ecc-strength: see nand.txt -- nand-ecc-step-size: see nand.txt - -The following ECC strength and step size are currently supported: - - nand-ecc-strength = <1>, nand-ecc-step-size = <512> (Hamming) - - nand-ecc-strength = <4>, nand-ecc-step-size = <512> (BCH4) - - nand-ecc-strength = <8>, nand-ecc-step-size = <512> (BCH8) (default) - -Example: - - fmc: nand-controller@58002000 { - compatible = "st,stm32mp15-fmc2"; - reg = <0x58002000 0x1000>, - <0x80000000 0x1000>, - <0x88010000 0x1000>, - <0x88020000 0x1000>, - <0x81000000 0x1000>, - <0x89010000 0x1000>, - <0x89020000 0x1000>; - interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&rcc FMC_K>; - resets = <&rcc FMC_R>; - pinctrl-names = "default"; - pinctrl-0 = <&fmc_pins_a>; - #address-cells = <1>; - #size-cells = <0>; - - nand@0 { - reg = <0>; - nand-on-flash-bbt; - #address-cells = <1>; - #size-cells = <1>; - }; - }; diff --git a/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt b/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt deleted file mode 100644 index edfe4b4..0000000 --- a/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt +++ /dev/null @@ -1,75 +0,0 @@ -STMicroelectronics STM32 USB HS PHY controller - -The STM32 USBPHYC block contains a dual port High Speed UTMI+ PHY and a UTMI -switch. It controls PHY configuration and status, and the UTMI+ switch that -selects either OTG or HOST controller for the second PHY port. It also sets -PLL configuration. - -USBPHYC - |_ PLL - | - |_ PHY port#1 _________________ HOST controller - | _ | - | / 1|________________| - |_ PHY port#2 ----| |________________ - | \_0| | - |_ UTMI switch_______| OTG controller - - -Phy provider node -================= - -Required properties: -- compatible: must be "st,stm32mp1-usbphyc" -- reg: address and length of the usb phy control register set -- clocks: phandle + clock specifier for the PLL phy clock -- vdda1v1-supply: phandle to the regulator providing 1V1 power to the PHY -- vdda1v8-supply: phandle to the regulator providing 1V8 power to the PHY -- #address-cells: number of address cells for phys sub-nodes, must be <1> -- #size-cells: number of size cells for phys sub-nodes, must be <0> - -Optional properties: -- assigned-clocks: phandle + clock specifier for the PLL phy clock -- assigned-clock-parents: the PLL phy clock parent -- resets: phandle + reset specifier - -Required nodes: one sub-node per port the controller provides. - -Phy sub-nodes -============== - -Required properties: -- reg: phy port index -- phy-supply: phandle to the regulator providing 3V3 power to the PHY, - see phy-bindings.txt in the same directory. -- #phy-cells: see phy-bindings.txt in the same directory, must be <0> for PHY - port#1 and must be <1> for PHY port#2, to select USB controller - -Optional properties: -- vbus-supply: phandle to the regulator providing 5V vbus to the USB connector - -Example: - usbphyc: usb-phy@5a006000 { - compatible = "st,stm32mp1-usbphyc"; - reg = <0x5a006000 0x1000>; - clocks = <&rcc_clk USBPHY_K>; - resets = <&rcc_rst USBPHY_R>; - #address-cells = <1>; - #size-cells = <0>; - - usbphyc_port0: usb-phy@0 { - reg = <0>; - phy-supply = <&vdd_usb>; - vdda1v1-supply = <®11>; - vdda1v8-supply = <®18> - #phy-cells = <0>; - }; - - usbphyc_port1: usb-phy@1 { - reg = <1>; - phy-supply = <&vdd_usb>; - vdda1v1-supply = <®11>; - vdda1v8-supply = <®18> - #phy-cells = <1>; - }; - }; diff --git a/doc/device-tree-bindings/pinctrl/st,stm32-pinctrl.txt b/doc/device-tree-bindings/pinctrl/st,stm32-pinctrl.txt deleted file mode 100644 index 0016925..0000000 --- a/doc/device-tree-bindings/pinctrl/st,stm32-pinctrl.txt +++ /dev/null @@ -1,208 +0,0 @@ -* STM32 GPIO and Pin Mux/Config controller - -STMicroelectronics's STM32 MCUs intregrate a GPIO and Pin mux/config hardware -controller. It controls the input/output settings on the available pins and -also provides ability to multiplex and configure the output of various on-chip -controllers onto these pads. - -Pin controller node: -Required properies: - - compatible: value should be one of the following: - "st,stm32f429-pinctrl" - "st,stm32f469-pinctrl" - "st,stm32f746-pinctrl" - "st,stm32f769-pinctrl" - "st,stm32h743-pinctrl" - "st,stm32mp157-pinctrl" - "st,stm32mp157-z-pinctrl" - - #address-cells: The value of this property must be 1 - - #size-cells : The value of this property must be 1 - - ranges : defines mapping between pin controller node (parent) to - gpio-bank node (children). - - pins-are-numbered: Specify the subnodes are using numbered pinmux to - specify pins. - -GPIO controller/bank node: -Required properties: - - gpio-controller : Indicates this device is a GPIO controller - - #gpio-cells : Should be two. - The first cell is the pin number - The second one is the polarity: - - 0 for active high - - 1 for active low - - reg : The gpio address range, relative to the pinctrl range - - clocks : clock that drives this bank - - st,bank-name : Should be a name string for this bank as specified in - the datasheet - -Optional properties: - - reset: : Reference to the reset controller - - st,syscfg: Should be phandle/offset/mask. - -The phandle to the syscon node which includes IRQ mux selection register. - -The offset of the IRQ mux selection register - -The field mask of IRQ mux, needed if different of 0xf. - - gpio-ranges: Define a dedicated mapping between a pin-controller and - a gpio controller. Format is <&phandle a b c> with: - -(phandle): phandle of pin-controller. - -(a): gpio base offset in range. - -(b): pin base offset in range. - -(c): gpio count in range - This entry has to be used either if there are holes inside a bank: - GPIOB0/B1/B2/B14/B15 (see example 2) - or if banks are not contiguous: - GPIOA/B/C/E... - NOTE: If "gpio-ranges" is used for a gpio controller, all gpio-controller - have to use a "gpio-ranges" entry. - More details in Documentation/devicetree/bindings/gpio/gpio.txt. - - st,bank-ioport: should correspond to the EXTI IOport selection (EXTI line - used to select GPIOs as interrupts). - - hwlocks: reference to a phandle of a hardware spinlock provider node. - - st,package: Indicates the SOC package used. - More details in include/dt-bindings/pinctrl/stm32-pinfunc.h - -Example 1: -#include <dt-bindings/pinctrl/stm32f429-pinfunc.h> -... - - pin-controller { - #address-cells = <1>; - #size-cells = <1>; - compatible = "st,stm32f429-pinctrl"; - ranges = <0 0x40020000 0x3000>; - pins-are-numbered; - - gpioa: gpio@40020000 { - gpio-controller; - #gpio-cells = <2>; - reg = <0x0 0x400>; - resets = <&reset_ahb1 0>; - st,bank-name = "GPIOA"; - }; - ... - pin-functions nodes follow... - }; - -Example 2: -#include <dt-bindings/pinctrl/stm32f429-pinfunc.h> -... - - pinctrl: pin-controller { - #address-cells = <1>; - #size-cells = <1>; - compatible = "st,stm32f429-pinctrl"; - ranges = <0 0x40020000 0x3000>; - pins-are-numbered; - - gpioa: gpio@40020000 { - gpio-controller; - #gpio-cells = <2>; - reg = <0x0 0x400>; - resets = <&reset_ahb1 0>; - st,bank-name = "GPIOA"; - gpio-ranges = <&pinctrl 0 0 16>; - }; - - gpiob: gpio@40020400 { - gpio-controller; - #gpio-cells = <2>; - reg = <0x0 0x400>; - resets = <&reset_ahb1 0>; - st,bank-name = "GPIOB"; - ngpios = 4; - gpio-ranges = <&pinctrl 0 16 3>, - <&pinctrl 14 30 2>; - }; - - - ... - pin-functions nodes follow... - }; - - -Contents of function subnode node: ----------------------------------- -Subnode format -A pinctrl node should contain at least one subnode representing the -pinctrl group available on the machine. Each subnode will list the -pins it needs, and how they should be configured, with regard to muxer -configuration, pullups, drive, output high/low and output speed. - - node { - pinmux = <PIN_NUMBER_PINMUX>; - GENERIC_PINCONFIG; - }; - -Required properties: -- pinmux: integer array, represents gpio pin number and mux setting. - Supported pin number and mux varies for different SoCs, and are defined in - dt-bindings/pinctrl/<soc>-pinfunc.h directly. - These defines are calculated as: - ((port * 16 + line) << 8) | function - With: - - port: The gpio port index (PA = 0, PB = 1, ..., PK = 11) - - line: The line offset within the port (PA0 = 0, PA1 = 1, ..., PA15 = 15) - - function: The function number, can be: - * 0 : GPIO - * 1 : Alternate Function 0 - * 2 : Alternate Function 1 - * 3 : Alternate Function 2 - * ... - * 16 : Alternate Function 15 - * 17 : Analog - - To simplify the usage, macro is available to generate "pinmux" field. - This macro is available here: - - include/dt-bindings/pinctrl/stm32-pinfunc.h - - Some examples of using macro: - /* GPIO A9 set as alernate function 2 */ - ... { - pinmux = <STM32_PINMUX('A', 9, AF2)>; - }; - /* GPIO A9 set as GPIO */ - ... { - pinmux = <STM32_PINMUX('A', 9, GPIO)>; - }; - /* GPIO A9 set as analog */ - ... { - pinmux = <STM32_PINMUX('A', 9, ANALOG)>; - }; - -Optional properties: -- GENERIC_PINCONFIG: is the generic pinconfig options to use. - Available options are: - - bias-disable, - - bias-pull-down, - - bias-pull-up, - - drive-push-pull, - - drive-open-drain, - - output-low - - output-high - - slew-rate = <x>, with x being: - < 0 > : Low speed - < 1 > : Medium speed - < 2 > : Fast speed - < 3 > : High speed - -Example: - -pin-controller { -... - usart1_pins_a: usart1@0 { - pins1 { - pinmux = <STM32_PINMUX('A', 9, AF7)>; - bias-disable; - drive-push-pull; - slew-rate = <0>; - }; - pins2 { - pinmux = <STM32_PINMUX('A', 10, AF7)>; - bias-disable; - }; - }; -}; - -&usart1 { - pinctrl-0 = <&usart1_pins_a>; - pinctrl-names = "default"; -}; diff --git a/doc/device-tree-bindings/regulator/st,stm32-vrefbuf.txt b/doc/device-tree-bindings/regulator/st,stm32-vrefbuf.txt deleted file mode 100644 index 0f6b6fe..0000000 --- a/doc/device-tree-bindings/regulator/st,stm32-vrefbuf.txt +++ /dev/null @@ -1,23 +0,0 @@ -STM32 VREFBUF - Voltage reference buffer - -Some STM32 devices embed a voltage reference buffer which can be used as -voltage reference for ADCs, DACs and also as voltage reference for external -components through the dedicated VREF+ pin. - -Required properties: -- compatible: Must be "st,stm32-vrefbuf". -- reg: Offset and length of VREFBUF register set. -- clocks: Must contain an entry for peripheral clock. - -Optional properties: -- vdda-supply: Phandle to the parent vdda supply regulator node. - -Example: - vrefbuf: regulator@58003c00 { - compatible = "st,stm32-vrefbuf"; - reg = <0x58003C00 0x8>; - clocks = <&rcc VREF_CK>; - regulator-min-microvolt = <1500000>; - regulator-max-microvolt = <2500000>; - vdda-supply = <&vdda>; - }; diff --git a/doc/device-tree-bindings/reset/st,stm32-rcc.txt b/doc/device-tree-bindings/reset/st,stm32-rcc.txt deleted file mode 100644 index 01db343..0000000 --- a/doc/device-tree-bindings/reset/st,stm32-rcc.txt +++ /dev/null @@ -1,6 +0,0 @@ -STMicroelectronics STM32 Peripheral Reset Controller -==================================================== - -The RCC IP is both a reset and a clock controller. - -Please see Documentation/devicetree/bindings/clock/st,stm32-rcc.txt diff --git a/doc/device-tree-bindings/spi/spi-stm32-qspi.txt b/doc/device-tree-bindings/spi/spi-stm32-qspi.txt deleted file mode 100644 index adeeb63..0000000 --- a/doc/device-tree-bindings/spi/spi-stm32-qspi.txt +++ /dev/null @@ -1,44 +0,0 @@ -* STMicroelectronics Quad Serial Peripheral Interface(QSPI) - -Required properties: -- compatible: should be "st,stm32f469-qspi" -- reg: the first contains the register location and length. - the second contains the memory mapping address and length -- reg-names: should contain the reg names "qspi" "qspi_mm" -- interrupts: should contain the interrupt for the device -- clocks: the phandle of the clock needed by the QSPI controller -- A pinctrl must be defined to set pins in mode of operation for QSPI transfer - -Optional properties: -- resets: must contain the phandle to the reset controller. - -A spi flash (NOR/NAND) must be a child of spi node and could have some -properties. Also see jedec,spi-nor.txt. - -Required properties: -- reg: chip-Select number (QSPI controller may connect 2 flashes) -- spi-max-frequency: max frequency of spi bus - -Optional property: -- spi-rx-bus-width: see ./spi-bus.txt for the description - -Example: - -qspi: spi@a0001000 { - compatible = "st,stm32f469-qspi"; - reg = <0xa0001000 0x1000>, <0x90000000 0x10000000>; - reg-names = "qspi", "qspi_mm"; - interrupts = <91>; - resets = <&rcc STM32F4_AHB3_RESET(QSPI)>; - clocks = <&rcc 0 STM32F4_AHB3_CLOCK(QSPI)>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_qspi0>; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-rx-bus-width = <4>; - spi-max-frequency = <108000000>; - ... - }; -}; diff --git a/doc/sphinx/kerneldoc.py b/doc/sphinx/kerneldoc.py index e9857ab..8189c33 100644 --- a/doc/sphinx/kerneldoc.py +++ b/doc/sphinx/kerneldoc.py @@ -37,18 +37,8 @@ import glob from docutils import nodes, statemachine from docutils.statemachine import ViewList from docutils.parsers.rst import directives, Directive - -# -# AutodocReporter is only good up to Sphinx 1.7 -# import sphinx - -Use_SSI = sphinx.__version__[:3] >= '1.7' -if Use_SSI: - from sphinx.util.docutils import switch_source_input -else: - from sphinx.ext.autodoc import AutodocReporter - +from sphinx.util.docutils import switch_source_input import kernellog __version__ = '1.0' @@ -163,18 +153,8 @@ class KernelDocDirective(Directive): return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] def do_parse(self, result, node): - if Use_SSI: - with switch_source_input(self.state, result): - self.state.nested_parse(result, 0, node, match_titles=1) - else: - save = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter - self.state.memo.reporter = AutodocReporter(result, self.state.memo.reporter) - self.state.memo.title_styles, self.state.memo.section_level = [], 0 - try: - self.state.nested_parse(result, 0, node, match_titles=1) - finally: - self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = save - + with switch_source_input(self.state, result): + self.state.nested_parse(result, 0, node, match_titles=1) def setup(app): app.add_config_value('kerneldoc_bin', None, 'env') diff --git a/include/efi_api.h b/include/efi_api.h index e854a8b..38ac47f 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -523,6 +523,7 @@ struct efi_device_path_acpi_path { # define DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS 0x0f # define DEVICE_PATH_SUB_TYPE_MSG_SATA 0x12 # define DEVICE_PATH_SUB_TYPE_MSG_NVME 0x17 +# define DEVICE_PATH_SUB_TYPE_MSG_URI 0x18 # define DEVICE_PATH_SUB_TYPE_MSG_SD 0x1a # define DEVICE_PATH_SUB_TYPE_MSG_MMC 0x1d @@ -587,6 +588,11 @@ struct efi_device_path_nvme { u8 eui64[8]; } __packed; +struct efi_device_path_uri { + struct efi_device_path dp; + u8 uri[]; +} __packed; + #define DEVICE_PATH_TYPE_MEDIA_DEVICE 0x04 # define DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH 0x01 # define DEVICE_PATH_SUB_TYPE_CDROM_PATH 0x02 diff --git a/include/efi_loader.h b/include/efi_loader.h index a120d94..32cb8d0 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -499,6 +499,11 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size); efi_status_t efi_init_variables(void); /* Notify ExitBootServices() is called */ void efi_variables_boot_exit_notify(void); +efi_status_t efi_tcg2_notify_exit_boot_services_failed(void); +/* Measure efi application invocation */ +efi_status_t efi_tcg2_measure_efi_app_invocation(void); +/* Measure efi application exit */ +efi_status_t efi_tcg2_measure_efi_app_exit(void); /* Called by bootefi to initialize root node */ efi_status_t efi_root_node_register(void); /* Called by bootefi to initialize runtime */ diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h index bcfb981..497ba3c 100644 --- a/include/efi_tcg2.h +++ b/include/efi_tcg2.h @@ -142,6 +142,26 @@ struct efi_tcg2_final_events_table { struct tcg_pcr_event2 event[]; }; +/** + * struct tdUEFI_VARIABLE_DATA - event log structure of UEFI variable + * @variable_name: The vendorGUID parameter in the + * GetVariable() API. + * @unicode_name_length: The length in CHAR16 of the Unicode name of + * the variable. + * @variable_data_length: The size of the variable data. + * @unicode_name: The CHAR16 unicode name of the variable + * without NULL-terminator. + * @variable_data: The data parameter of the efi variable + * in the GetVariable() API. + */ +struct efi_tcg2_uefi_variable_data { + efi_guid_t variable_name; + u64 unicode_name_length; + u64 variable_data_length; + u16 unicode_name[1]; + u8 variable_data[1]; +}; + struct efi_tcg2_protocol { efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this, struct efi_tcg2_boot_service_capability *capability); diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 949a13c..13b3db6 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -75,7 +75,7 @@ struct udevice; /* * event types, cf. * "TCG PC Client Platform Firmware Profile Specification", Family "2.0" - * rev 1.04, June 3, 2019 + * Level 00 Version 1.05 Revision 23, May 7, 2021 */ #define EV_EFI_EVENT_BASE ((u32)0x80000000) #define EV_EFI_VARIABLE_DRIVER_CONFIG ((u32)0x80000001) @@ -87,8 +87,24 @@ struct udevice; #define EV_EFI_ACTION ((u32)0x80000007) #define EV_EFI_PLATFORM_FIRMWARE_BLOB ((u32)0x80000008) #define EV_EFI_HANDOFF_TABLES ((u32)0x80000009) +#define EV_EFI_PLATFORM_FIRMWARE_BLOB2 ((u32)0x8000000A) +#define EV_EFI_HANDOFF_TABLES2 ((u32)0x8000000B) +#define EV_EFI_VARIABLE_BOOT2 ((u32)0x8000000C) #define EV_EFI_HCRTM_EVENT ((u32)0x80000010) #define EV_EFI_VARIABLE_AUTHORITY ((u32)0x800000E0) +#define EV_EFI_SPDM_FIRMWARE_BLOB ((u32)0x800000E1) +#define EV_EFI_SPDM_FIRMWARE_CONFIG ((u32)0x800000E2) + +#define EFI_CALLING_EFI_APPLICATION \ + "Calling EFI Application from Boot Option" +#define EFI_RETURNING_FROM_EFI_APPLICATION \ + "Returning from EFI Application from Boot Option" +#define EFI_EXIT_BOOT_SERVICES_INVOCATION \ + "Exit Boot Services Invocation" +#define EFI_EXIT_BOOT_SERVICES_FAILED \ + "Exit Boot Services Returned with Failure" +#define EFI_EXIT_BOOT_SERVICES_SUCCEEDED \ + "Exit Boot Services Returned with Success" /* TPMS_TAGGED_PROPERTY Structure */ struct tpms_tagged_property { diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 0b98e91..f0283b5 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -2182,6 +2182,11 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, efi_set_watchdog(0); WATCHDOG_RESET(); out: + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { + if (ret != EFI_SUCCESS) + efi_tcg2_notify_exit_boot_services_failed(); + } + return EFI_EXIT(ret); } @@ -2994,6 +2999,16 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, image_obj->exit_status = &exit_status; image_obj->exit_jmp = &exit_jmp; + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { + ret = efi_tcg2_measure_efi_app_invocation(); + if (ret != EFI_SUCCESS) { + log_warning("tcg2 measurement fails(0x%lx)\n", + ret); + } + } + } + /* call the image! */ if (setjmp(&exit_jmp)) { /* @@ -3252,6 +3267,16 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, exit_status != EFI_SUCCESS) efi_delete_image(image_obj, loaded_image_protocol); + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { + if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { + ret = efi_tcg2_measure_efi_app_exit(); + if (ret != EFI_SUCCESS) { + log_warning("tcg2 measurement fails(0x%lx)\n", + ret); + } + } + } + /* Make sure entry/exit counts for EFI world cross-overs match */ EFI_EXIT(exit_status); diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index 675e80b..d46327a 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -190,6 +190,19 @@ static char *dp_msging(char *s, struct efi_device_path *dp) break; } + case DEVICE_PATH_SUB_TYPE_MSG_URI: { + struct efi_device_path_uri *udp = + (struct efi_device_path_uri *)dp; + int n; + + n = (int)udp->dp.length - sizeof(struct efi_device_path_uri); + + s += sprintf(s, "Uri("); + if (n > 0 && n < MAX_NODE_LEN - 6) + s += snprintf(s, n, "%s", (char *)udp->uri); + s += sprintf(s, ")"); + break; + } case DEVICE_PATH_SUB_TYPE_MSG_SD: case DEVICE_PATH_SUB_TYPE_MSG_MMC: { const char *typename = diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 1319a8b..35e69b9 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -35,6 +35,7 @@ struct event_log_buffer { }; static struct event_log_buffer event_log; +static bool tcg2_efi_app_invoked; /* * When requesting TPM2_CAP_TPM_PROPERTIES the value is on a standard offset. * Since the current tpm2_get_capability() response buffers starts at @@ -78,6 +79,19 @@ static const struct digest_info hash_algo_list[] = { }, }; +struct variable_info { + u16 *name; + const efi_guid_t *guid; +}; + +static struct variable_info secure_variables[] = { + {L"SecureBoot", &efi_global_variable_guid}, + {L"PK", &efi_global_variable_guid}, + {L"KEK", &efi_global_variable_guid}, + {L"db", &efi_guid_image_security_database}, + {L"dbx", &efi_guid_image_security_database}, +}; + #define MAX_HASH_COUNT ARRAY_SIZE(hash_algo_list) /** @@ -1265,6 +1279,39 @@ free_pool: } /** + * tcg2_measure_event() - common function to add event log and extend PCR + * + * @dev: TPM device + * @pcr_index: PCR index + * @event_type: type of event added + * @size: event size + * @event: event data + * + * Return: status code + */ +static efi_status_t +tcg2_measure_event(struct udevice *dev, u32 pcr_index, u32 event_type, + u32 size, u8 event[]) +{ + struct tpml_digest_values digest_list; + efi_status_t ret; + + ret = tcg2_create_digest(event, size, &digest_list); + if (ret != EFI_SUCCESS) + goto out; + + ret = tcg2_pcr_extend(dev, pcr_index, &digest_list); + if (ret != EFI_SUCCESS) + goto out; + + ret = tcg2_agile_log_append(pcr_index, event_type, &digest_list, + size, event); + +out: + return ret; +} + +/** * efi_append_scrtm_version - Append an S-CRTM EV_S_CRTM_VERSION event on the * eventlog and extend the PCRs * @@ -1274,27 +1321,308 @@ free_pool: */ static efi_status_t efi_append_scrtm_version(struct udevice *dev) { - struct tpml_digest_values digest_list; u8 ver[] = U_BOOT_VERSION_STRING; - const int pcr_index = 0; efi_status_t ret; - ret = tcg2_create_digest(ver, sizeof(ver), &digest_list); + ret = tcg2_measure_event(dev, 0, EV_S_CRTM_VERSION, sizeof(ver), ver); + + return ret; +} + +/** + * tcg2_measure_variable() - add variable event log and extend PCR + * + * @dev: TPM device + * @pcr_index: PCR index + * @event_type: type of event added + * @var_name: variable name + * @guid: guid + * @data_size: variable data size + * @data: variable data + * + * Return: status code + */ +static efi_status_t tcg2_measure_variable(struct udevice *dev, u32 pcr_index, + u32 event_type, u16 *var_name, + const efi_guid_t *guid, + efi_uintn_t data_size, u8 *data) +{ + u32 event_size; + efi_status_t ret; + struct efi_tcg2_uefi_variable_data *event; + + event_size = sizeof(event->variable_name) + + sizeof(event->unicode_name_length) + + sizeof(event->variable_data_length) + + (u16_strlen(var_name) * sizeof(u16)) + data_size; + event = malloc(event_size); + if (!event) + return EFI_OUT_OF_RESOURCES; + + guidcpy(&event->variable_name, guid); + event->unicode_name_length = u16_strlen(var_name); + event->variable_data_length = data_size; + memcpy(event->unicode_name, var_name, + (event->unicode_name_length * sizeof(u16))); + if (data) { + memcpy((u16 *)event->unicode_name + event->unicode_name_length, + data, data_size); + } + ret = tcg2_measure_event(dev, pcr_index, event_type, event_size, + (u8 *)event); + free(event); + return ret; +} + +/** + * tcg2_measure_boot_variable() - measure boot variables + * + * @dev: TPM device + * + * Return: status code + */ +static efi_status_t tcg2_measure_boot_variable(struct udevice *dev) +{ + u16 *boot_order; + u16 *boot_index; + u16 var_name[] = L"BootOrder"; + u16 boot_name[] = L"Boot####"; + u8 *bootvar; + efi_uintn_t var_data_size; + u32 count, i; + efi_status_t ret; + + boot_order = efi_get_var(var_name, &efi_global_variable_guid, + &var_data_size); + if (!boot_order) { + ret = EFI_NOT_FOUND; + goto error; + } + + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, var_name, + &efi_global_variable_guid, var_data_size, + (u8 *)boot_order); + if (ret != EFI_SUCCESS) + goto error; + + count = var_data_size / sizeof(*boot_order); + boot_index = boot_order; + for (i = 0; i < count; i++) { + efi_create_indexed_name(boot_name, sizeof(boot_name), + "Boot", *boot_index++); + + bootvar = efi_get_var(boot_name, &efi_global_variable_guid, + &var_data_size); + + if (!bootvar) { + log_info("%ls not found\n", boot_name); + continue; + } + + ret = tcg2_measure_variable(dev, 1, EV_EFI_VARIABLE_BOOT2, + boot_name, + &efi_global_variable_guid, + var_data_size, bootvar); + free(bootvar); + if (ret != EFI_SUCCESS) + goto error; + } + +error: + free(boot_order); + return ret; +} + +/** + * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation + * + * Return: status code + */ +efi_status_t efi_tcg2_measure_efi_app_invocation(void) +{ + efi_status_t ret; + u32 pcr_index; + struct udevice *dev; + u32 event = 0; + + if (tcg2_efi_app_invoked) + return EFI_SUCCESS; + + ret = platform_get_tpm2_device(&dev); + if (ret != EFI_SUCCESS) + return ret; + + ret = tcg2_measure_boot_variable(dev); if (ret != EFI_SUCCESS) goto out; - ret = tcg2_pcr_extend(dev, pcr_index, &digest_list); + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, + strlen(EFI_CALLING_EFI_APPLICATION), + (u8 *)EFI_CALLING_EFI_APPLICATION); if (ret != EFI_SUCCESS) goto out; - ret = tcg2_agile_log_append(pcr_index, EV_S_CRTM_VERSION, &digest_list, - sizeof(ver), ver); + for (pcr_index = 0; pcr_index <= 7; pcr_index++) { + ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR, + sizeof(event), (u8 *)&event); + if (ret != EFI_SUCCESS) + goto out; + } + tcg2_efi_app_invoked = true; out: return ret; } /** + * efi_tcg2_measure_efi_app_exit() - measure efi app exit + * + * Return: status code + */ +efi_status_t efi_tcg2_measure_efi_app_exit(void) +{ + efi_status_t ret; + struct udevice *dev; + + ret = platform_get_tpm2_device(&dev); + if (ret != EFI_SUCCESS) + return ret; + + ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION, + strlen(EFI_RETURNING_FROM_EFI_APPLICATION), + (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION); + return ret; +} + +/** + * efi_tcg2_notify_exit_boot_services() - ExitBootService callback + * + * @event: callback event + * @context: callback context + */ +static void EFIAPI +efi_tcg2_notify_exit_boot_services(struct efi_event *event, void *context) +{ + efi_status_t ret; + struct udevice *dev; + + EFI_ENTRY("%p, %p", event, context); + + ret = platform_get_tpm2_device(&dev); + if (ret != EFI_SUCCESS) + goto out; + + ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION, + strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION), + (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION); + if (ret != EFI_SUCCESS) + goto out; + + ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION, + strlen(EFI_EXIT_BOOT_SERVICES_SUCCEEDED), + (u8 *)EFI_EXIT_BOOT_SERVICES_SUCCEEDED); + +out: + EFI_EXIT(ret); +} + +/** + * efi_tcg2_notify_exit_boot_services_failed() + * - notify ExitBootServices() is failed + * + * Return: status code + */ +efi_status_t efi_tcg2_notify_exit_boot_services_failed(void) +{ + struct udevice *dev; + efi_status_t ret; + + ret = platform_get_tpm2_device(&dev); + if (ret != EFI_SUCCESS) + goto out; + + ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION, + strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION), + (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION); + if (ret != EFI_SUCCESS) + goto out; + + ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION, + strlen(EFI_EXIT_BOOT_SERVICES_FAILED), + (u8 *)EFI_EXIT_BOOT_SERVICES_FAILED); + +out: + return ret; +} + +/** + * tcg2_measure_secure_boot_variable() - measure secure boot variables + * + * @dev: TPM device + * + * Return: status code + */ +static efi_status_t tcg2_measure_secure_boot_variable(struct udevice *dev) +{ + u8 *data; + efi_uintn_t data_size; + u32 count, i; + efi_status_t ret; + + count = ARRAY_SIZE(secure_variables); + for (i = 0; i < count; i++) { + /* + * According to the TCG2 PC Client PFP spec, "SecureBoot", + * "PK", "KEK", "db" and "dbx" variables must be measured + * even if they are empty. + */ + data = efi_get_var(secure_variables[i].name, + secure_variables[i].guid, + &data_size); + + ret = tcg2_measure_variable(dev, 7, + EV_EFI_VARIABLE_DRIVER_CONFIG, + secure_variables[i].name, + secure_variables[i].guid, + data_size, data); + free(data); + if (ret != EFI_SUCCESS) + goto error; + } + + /* + * TCG2 PC Client PFP spec says "dbt" and "dbr" are + * measured if present and not empty. + */ + data = efi_get_var(L"dbt", + &efi_guid_image_security_database, + &data_size); + if (data) { + ret = tcg2_measure_variable(dev, 7, + EV_EFI_VARIABLE_DRIVER_CONFIG, + L"dbt", + &efi_guid_image_security_database, + data_size, data); + free(data); + } + + data = efi_get_var(L"dbr", + &efi_guid_image_security_database, + &data_size); + if (data) { + ret = tcg2_measure_variable(dev, 7, + EV_EFI_VARIABLE_DRIVER_CONFIG, + L"dbr", + &efi_guid_image_security_database, + data_size, data); + free(data); + } + +error: + return ret; +} + +/** * efi_tcg2_register() - register EFI_TCG2_PROTOCOL * * If a TPM2 device is available, the TPM TCG2 Protocol is registered @@ -1305,6 +1633,7 @@ efi_status_t efi_tcg2_register(void) { efi_status_t ret = EFI_SUCCESS; struct udevice *dev; + struct efi_event *event; ret = platform_get_tpm2_device(&dev); if (ret != EFI_SUCCESS) { @@ -1328,6 +1657,21 @@ efi_status_t efi_tcg2_register(void) tcg2_uninit(); goto fail; } + + ret = efi_create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK, + efi_tcg2_notify_exit_boot_services, NULL, + NULL, &event); + if (ret != EFI_SUCCESS) { + tcg2_uninit(); + goto fail; + } + + ret = tcg2_measure_secure_boot_variable(dev); + if (ret != EFI_SUCCESS) { + tcg2_uninit(); + goto fail; + } + return ret; fail: |