Re: [U-Boot] [PATCH] ARM: aspeed: Add SD host controller driver
On 8/13/19 11:55 AM, Cédric Le Goater wrote: On 13/08/2019 08:41, Peng Fan wrote: Subject: [U-Boot][PATCH] ARM: aspeed: Add SD host controller driver Add support for the Aspeed SD host controller engine. This involves adding an MMC SDHCI driver and various additions to the clock and reset drivers for Aspeed chips. Signed-off-by: Eddie James --- arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 3 + arch/arm/include/asm/gpio.h| 3 +- arch/arm/mach-aspeed/ast2500-board.c | 3 + drivers/clk/aspeed/clk_ast2500.c | 27 + drivers/mmc/Kconfig| 11 drivers/mmc/Makefile | 1 + drivers/mmc/aspeed_sdhci.c | 78 Please split the patch. yes. a clock patch, a driver patch, a board integration patch at least, with some DT addons for the EVB. Don't we want to sync up the DT from Linux also ? The Linux one uses a parent node for the whole Aspeed SD controller and child nodes for the all the SD card slots. We don't need that parent driver in U-Boot and also it seems complicated (i.e. I couldn't figure out how) to probe up child nodes with the U-Boot driver model. Thanks, Eddie Thanks, C. Thanks, Peng. ++ drivers/pinctrl/aspeed/pinctrl_ast2500.c | 2 + 8 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/aspeed_sdhci.c diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h index 4988ced..8db4901 100644 --- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h +++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h @@ -22,6 +22,8 @@ #define SCU_MPLL_POST_MASK(0x3f << SCU_MPLL_POST_SHIFT) #define SCU_PCLK_DIV_SHIFT23 #define SCU_PCLK_DIV_MASK (7 << SCU_PCLK_DIV_SHIFT) +#define SCU_SDCLK_DIV_SHIFT12 +#define SCU_SDCLK_DIV_MASK (7 << SCU_SDCLK_DIV_SHIFT) #define SCU_HPLL_DENUM_SHIFT 0 #define SCU_HPLL_DENUM_MASK 0x1f #define SCU_HPLL_NUM_SHIFT5 @@ -107,6 +109,7 @@ #define SCU_CLKSTOP_MAC1 (1 << 20) #define SCU_CLKSTOP_MAC2 (1 << 21) +#define SCU_CLKSTOP_SDCLK (1 << 27) #define SCU_D2PLL_EXT1_OFF(1 << 0) #define SCU_D2PLL_EXT1_BYPASS (1 << 1) diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h index 370031f..38a5922 100644 --- a/arch/arm/include/asm/gpio.h +++ b/arch/arm/include/asm/gpio.h @@ -1,6 +1,7 @@ #if !defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARCH_STI) && \ !defined(CONFIG_ARCH_K3) && !defined(CONFIG_ARCH_BCM6858) && \ - !defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) + !defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) && \ + !defined(CONFIG_ARCH_ASPEED) #include #endif #include diff --git a/arch/arm/mach-aspeed/ast2500-board.c b/arch/arm/mach-aspeed/ast2500-board.c index e7edd54..52a4e05 100644 --- a/arch/arm/mach-aspeed/ast2500-board.c +++ b/arch/arm/mach-aspeed/ast2500-board.c @@ -4,6 +4,7 @@ */ #include #include +#include #include #include #include @@ -55,6 +56,8 @@ int board_init(void) { gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; + mmc_initialize(gd->bd); + return 0; } diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c index dbee13a..9249cf9 100644 --- a/drivers/clk/aspeed/clk_ast2500.c +++ b/drivers/clk/aspeed/clk_ast2500.c @@ -143,6 +143,17 @@ static ulong ast2500_clk_get_rate(struct clk *clk) rate = rate / apb_div; } break; + case BCLK_SDCLK: + { + ulong apb_div = 4 + 4 * ((readl(>scu->clk_sel1) + & SCU_SDCLK_DIV_MASK) +>> SCU_SDCLK_DIV_SHIFT); + rate = ast2500_get_hpll_rate(clkin, +readl(> + scu->h_pll_param)); + rate = rate / apb_div; + } + break; case PCLK_UART1: rate = ast2500_get_uart_clk_rate(priv->scu, 1); break; @@ -436,6 +447,22 @@ static int ast2500_clk_enable(struct clk *clk) struct ast2500_clk_priv *priv = dev_get_priv(clk->dev); switch (clk->id) { + case BCLK_SDCLK: + if (readl(>scu->clk_stop_ctrl1) & SCU_CLKSTOP_SDCLK) { + ast_scu_unlock(priv->scu); + + setbits_le32(>scu->sysr
[U-Boot] [PATCH v2 2/4] mmc: Add Aspeed SD controller driver
Add support for the Aspeed SD host controller engine. Signed-off-by: Eddie James --- drivers/mmc/Kconfig| 11 +++ drivers/mmc/Makefile | 1 + drivers/mmc/aspeed_sdhci.c | 78 ++ 3 files changed, 90 insertions(+) create mode 100644 drivers/mmc/aspeed_sdhci.c diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index c6812f6..536f66a 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -421,6 +421,17 @@ config SPL_MMC_SDHCI_ADMA This enables support for the ADMA (Advanced DMA) defined in the SD Host Controller Standard Specification Version 3.00 in SPL. +config MMC_SDHCI_ASPEED + bool "Aspeed SDHCI controller" + depends on ARCH_ASPEED + depends on DM_MMC + depends on MMC_SDHCI + help + Enables support for the Aspeed SDHCI 2.0 controller present on Aspeed + SoCs. This device is compatible with SD 3.0 and/or MMC 4.3 + specifications. On the AST2600, the device is also compatible with + MMC 5.1 and eMMC 3.0. + config MMC_SDHCI_ATMEL bool "Atmel SDHCI controller support" depends on ARCH_AT91 diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 6cc018b..5594195 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o # SDHCI obj-$(CONFIG_MMC_SDHCI)+= sdhci.o +obj-$(CONFIG_MMC_SDHCI_ASPEED) += aspeed_sdhci.o obj-$(CONFIG_MMC_SDHCI_ATMEL) += atmel_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCM2835)+= bcm2835_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCMSTB) += bcmstb_sdhci.o diff --git a/drivers/mmc/aspeed_sdhci.c b/drivers/mmc/aspeed_sdhci.c new file mode 100644 index 000..c292c42 --- /dev/null +++ b/drivers/mmc/aspeed_sdhci.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 IBM Corp. + * Eddie James + */ + +#include +#include +#include +#include +#include + +struct aspeed_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +static int aspeed_sdhci_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct aspeed_sdhci_plat *plat = dev_get_platdata(dev); + struct sdhci_host *host = dev_get_priv(dev); + u32 max_clk; + struct clk clk; + int ret; + + ret = clk_get_by_index(dev, 0, ); + if (ret) + return ret; + + ret = clk_enable(); + if (ret) + return ret; + + host->name = dev->name; + host->ioaddr = (void *)devfdt_get_addr(dev); + + max_clk = clk_get_rate(); + if (!max_clk) + return -EINVAL; + + host->max_clk = max_clk; + host->mmc = >mmc; + host->mmc->dev = dev; + host->mmc->priv = host; + upriv->mmc = host->mmc; + + ret = sdhci_setup_cfg(>cfg, host, 0, 0); + if (ret) + return ret; + + return sdhci_probe(dev); +} + +static int aspeed_sdhci_bind(struct udevice *dev) +{ + struct aspeed_sdhci_plat *plat = dev_get_platdata(dev); + + return sdhci_bind(dev, >mmc, >cfg); +} + +static const struct udevice_id aspeed_sdhci_ids[] = { + { .compatible = "aspeed,ast2400-sdhci" }, + { .compatible = "aspeed,ast2500-sdhci" }, + { .compatible = "aspeed,ast2600-sdhci" }, + { } +}; + +U_BOOT_DRIVER(aspeed_sdhci_drv) = { + .name = "aspeed_sdhci", + .id = UCLASS_MMC, + .of_match = aspeed_sdhci_ids, + .ops= _ops, + .bind = aspeed_sdhci_bind, + .probe = aspeed_sdhci_probe, + .priv_auto_alloc_size = sizeof(struct sdhci_host), + .platdata_auto_alloc_size = sizeof(struct aspeed_sdhci_plat), +}; -- 1.8.3.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 0/4] ARM: aspeed: Add SD host controller driver
This series adds support for the SD host controller on Aspeed ast2XXX SocS. It also enables MMC and the SD controller on the ast2500 EVB. Changes since v1: - split the patch up - Add defconfig and dts changes Eddie James (4): clk: aspeed: Add support for SD clock mmc: Add Aspeed SD controller driver aspeed: Support SD controller on the ast2500 board ARM: dts: ast2500: Add SDHCI nodes arch/arm/dts/ast2500-evb.dts | 14 + arch/arm/dts/ast2500-u-boot.dtsi | 16 ++ arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 3 + arch/arm/include/asm/gpio.h| 3 +- arch/arm/mach-aspeed/ast2500-board.c | 3 + configs/evb-ast2500_defconfig | 6 ++ drivers/clk/aspeed/clk_ast2500.c | 27 + drivers/mmc/Kconfig| 11 drivers/mmc/Makefile | 1 + drivers/mmc/aspeed_sdhci.c | 78 ++ drivers/pinctrl/aspeed/pinctrl_ast2500.c | 2 + 11 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/aspeed_sdhci.c -- 1.8.3.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 1/4] clk: aspeed: Add support for SD clock
Add code to enable the SD clock on the ast2500 SoC. Signed-off-by: Eddie James --- arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 3 +++ drivers/clk/aspeed/clk_ast2500.c | 27 ++ drivers/pinctrl/aspeed/pinctrl_ast2500.c | 2 ++ 3 files changed, 32 insertions(+) diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h index 4988ced..8db4901 100644 --- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h +++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h @@ -22,6 +22,8 @@ #define SCU_MPLL_POST_MASK (0x3f << SCU_MPLL_POST_SHIFT) #define SCU_PCLK_DIV_SHIFT 23 #define SCU_PCLK_DIV_MASK (7 << SCU_PCLK_DIV_SHIFT) +#define SCU_SDCLK_DIV_SHIFT12 +#define SCU_SDCLK_DIV_MASK (7 << SCU_SDCLK_DIV_SHIFT) #define SCU_HPLL_DENUM_SHIFT 0 #define SCU_HPLL_DENUM_MASK0x1f #define SCU_HPLL_NUM_SHIFT 5 @@ -107,6 +109,7 @@ #define SCU_CLKSTOP_MAC1 (1 << 20) #define SCU_CLKSTOP_MAC2 (1 << 21) +#define SCU_CLKSTOP_SDCLK (1 << 27) #define SCU_D2PLL_EXT1_OFF (1 << 0) #define SCU_D2PLL_EXT1_BYPASS (1 << 1) diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c index dbee13a..9249cf9 100644 --- a/drivers/clk/aspeed/clk_ast2500.c +++ b/drivers/clk/aspeed/clk_ast2500.c @@ -143,6 +143,17 @@ static ulong ast2500_clk_get_rate(struct clk *clk) rate = rate / apb_div; } break; + case BCLK_SDCLK: + { + ulong apb_div = 4 + 4 * ((readl(>scu->clk_sel1) + & SCU_SDCLK_DIV_MASK) +>> SCU_SDCLK_DIV_SHIFT); + rate = ast2500_get_hpll_rate(clkin, +readl(> + scu->h_pll_param)); + rate = rate / apb_div; + } + break; case PCLK_UART1: rate = ast2500_get_uart_clk_rate(priv->scu, 1); break; @@ -436,6 +447,22 @@ static int ast2500_clk_enable(struct clk *clk) struct ast2500_clk_priv *priv = dev_get_priv(clk->dev); switch (clk->id) { + case BCLK_SDCLK: + if (readl(>scu->clk_stop_ctrl1) & SCU_CLKSTOP_SDCLK) { + ast_scu_unlock(priv->scu); + + setbits_le32(>scu->sysreset_ctrl1, +SCU_SYSRESET_SDIO); + udelay(100); + clrbits_le32(>scu->clk_stop_ctrl1, +SCU_CLKSTOP_SDCLK); + mdelay(10); + clrbits_le32(>scu->sysreset_ctrl1, +SCU_SYSRESET_SDIO); + + ast_scu_lock(priv->scu); + } + break; /* * For MAC clocks the clock rate is * configured based on whether RGMII or RMII mode has been selected diff --git a/drivers/pinctrl/aspeed/pinctrl_ast2500.c b/drivers/pinctrl/aspeed/pinctrl_ast2500.c index ed333b9..a6e9c0d 100644 --- a/drivers/pinctrl/aspeed/pinctrl_ast2500.c +++ b/drivers/pinctrl/aspeed/pinctrl_ast2500.c @@ -58,6 +58,8 @@ static const struct ast2500_group_config ast2500_groups[] = { { "MDIO1", 3, (1 << 31) | (1 << 30) }, { "MAC2LINK", 1, (1 << 1) }, { "MDIO2", 5, (1 << 2) }, + { "SD1", 5, (1 << 0) }, + { "SD2", 5, (1 << 1) }, }; static int ast2500_pinctrl_get_groups_count(struct udevice *dev) -- 1.8.3.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 4/4] ARM: dts: ast2500: Add SDHCI nodes
Add nodes for the Aspeed SD controllers with their necessary properties. Signed-off-by: Eddie James --- arch/arm/dts/ast2500-evb.dts | 14 ++ arch/arm/dts/ast2500-u-boot.dtsi | 16 2 files changed, 30 insertions(+) diff --git a/arch/arm/dts/ast2500-evb.dts b/arch/arm/dts/ast2500-evb.dts index ebf44fd..4796ed4 100644 --- a/arch/arm/dts/ast2500-evb.dts +++ b/arch/arm/dts/ast2500-evb.dts @@ -59,3 +59,17 @@ pinctrl-names = "default"; pinctrl-0 = <_mac2link_default _mdio2_default>; }; + + { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <_sd1_default>; +}; + + { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <_sd2_default>; +}; diff --git a/arch/arm/dts/ast2500-u-boot.dtsi b/arch/arm/dts/ast2500-u-boot.dtsi index 7f80bad..8ac4215 100644 --- a/arch/arm/dts/ast2500-u-boot.dtsi +++ b/arch/arm/dts/ast2500-u-boot.dtsi @@ -34,6 +34,22 @@ apb { u-boot,dm-pre-reloc; + + sdhci0: sdhci@1e740100 { + compatible = "aspeed,ast2500-sdhci"; + reg = <0x1e740100>; + #reset-cells = <1>; + clocks = < BCLK_SDCLK>; + resets = < AST_RESET_SDIO>; + }; + + sdhci1: sdhci@1e740200 { + compatible = "aspeed,ast2500-sdhci"; + reg = <0x1e740200>; + #reset-cells = <1>; + clocks = < BCLK_SDCLK>; + resets = < AST_RESET_SDIO>; + }; }; }; -- 1.8.3.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 3/4] aspeed: Support SD controller on the ast2500 board
Initialize the MMC subsystem on the ast2500 board. Compile MMC and the Aspeed SD controller on the ast2500 EVB. Signed-off-by: Eddie James --- arch/arm/include/asm/gpio.h | 3 ++- arch/arm/mach-aspeed/ast2500-board.c | 3 +++ configs/evb-ast2500_defconfig| 6 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h index 370031f..38a5922 100644 --- a/arch/arm/include/asm/gpio.h +++ b/arch/arm/include/asm/gpio.h @@ -1,6 +1,7 @@ #if !defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARCH_STI) && \ !defined(CONFIG_ARCH_K3) && !defined(CONFIG_ARCH_BCM6858) && \ - !defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) + !defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) && \ + !defined(CONFIG_ARCH_ASPEED) #include #endif #include diff --git a/arch/arm/mach-aspeed/ast2500-board.c b/arch/arm/mach-aspeed/ast2500-board.c index e7edd54..52a4e05 100644 --- a/arch/arm/mach-aspeed/ast2500-board.c +++ b/arch/arm/mach-aspeed/ast2500-board.c @@ -4,6 +4,7 @@ */ #include #include +#include #include #include #include @@ -55,6 +56,8 @@ int board_init(void) { gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; + mmc_initialize(gd->bd); + return 0; } diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig index 59d41cb..bfa6b32 100644 --- a/configs/evb-ast2500_defconfig +++ b/configs/evb-ast2500_defconfig @@ -16,6 +16,7 @@ CONFIG_HUSH_PARSER=y CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y +CONFIG_CMD_MMC=y CONFIG_CMD_PING=y CONFIG_DEFAULT_DEVICE_TREE="ast2500-evb" CONFIG_NET_RANDOM_ETHADDR=y @@ -36,3 +37,8 @@ CONFIG_SYS_NS16550=y CONFIG_SYSRESET=y CONFIG_TIMER=y CONFIG_WDT=y +CONFIG_MMC=y +CONFIG_DM_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_ASPEED=y +CONFIG_MMC_VERBOSE=y -- 1.8.3.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v3 3/4] configs: AST2500 EVB: Enable SD controller
Enable the MMC subsystem and the Aspeed SD controller. Also enable the use of the device tree for probing the controller. Signed-off-by: Eddie James --- configs/evb-ast2500_defconfig | 8 1 file changed, 8 insertions(+) diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig index 59d41cb..b47ca5b 100644 --- a/configs/evb-ast2500_defconfig +++ b/configs/evb-ast2500_defconfig @@ -16,6 +16,7 @@ CONFIG_HUSH_PARSER=y CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y +CONFIG_CMD_MMC=y CONFIG_CMD_PING=y CONFIG_DEFAULT_DEVICE_TREE="ast2500-evb" CONFIG_NET_RANDOM_ETHADDR=y @@ -36,3 +37,10 @@ CONFIG_SYS_NS16550=y CONFIG_SYSRESET=y CONFIG_TIMER=y CONFIG_WDT=y +CONFIG_MMC=y +CONFIG_DM_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_ASPEED=y +CONFIG_MMC_VERBOSE=y +CONFIG_OF_CONTROL=y +CONFIG_OF_EMBED=y -- 1.8.3.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v3 0/4] ARM: Aspeed: Add SD host controller driver
This series adds support for the SD host controller on the Aspeed ast2xxx SocS. It also enables MMC and the SD controller for the ast2500 EVB. Changes since v2: - Remove mmc_initialize call in the ast2500 board init - Add OF_CONTROL to the ast2500 EVB configuration - Fix the clock-getting code in the driver probe function Changes since v1: - Split the patch up - Add defconfig and devicetree changes Eddie James (4): clk: aspeed: Add support for SD clock mmc: Add Aspeed SD controller driver configs: AST2500 EVB: Enable SD controller ARM: dts: ast2500: Add SDHCI nodes arch/arm/dts/ast2500-evb.dts | 14 arch/arm/dts/ast2500-u-boot.dtsi | 16 + arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 3 + arch/arm/include/asm/gpio.h| 3 +- configs/evb-ast2500_defconfig | 8 +++ drivers/clk/aspeed/clk_ast2500.c | 27 drivers/mmc/Kconfig| 11 drivers/mmc/Makefile | 1 + drivers/mmc/aspeed_sdhci.c | 90 ++ drivers/pinctrl/aspeed/pinctrl_ast2500.c | 2 + 10 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/aspeed_sdhci.c -- 1.8.3.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v3 1/4] clk: aspeed: Add support for SD clock
Add code to enable the SD clock on the ast2500 SoC. Reviewed-by: Cédric Le Goater Signed-off-by: Eddie James --- arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 3 +++ drivers/clk/aspeed/clk_ast2500.c | 27 ++ drivers/pinctrl/aspeed/pinctrl_ast2500.c | 2 ++ 3 files changed, 32 insertions(+) diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h index 4988ced..8db4901 100644 --- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h +++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h @@ -22,6 +22,8 @@ #define SCU_MPLL_POST_MASK (0x3f << SCU_MPLL_POST_SHIFT) #define SCU_PCLK_DIV_SHIFT 23 #define SCU_PCLK_DIV_MASK (7 << SCU_PCLK_DIV_SHIFT) +#define SCU_SDCLK_DIV_SHIFT12 +#define SCU_SDCLK_DIV_MASK (7 << SCU_SDCLK_DIV_SHIFT) #define SCU_HPLL_DENUM_SHIFT 0 #define SCU_HPLL_DENUM_MASK0x1f #define SCU_HPLL_NUM_SHIFT 5 @@ -107,6 +109,7 @@ #define SCU_CLKSTOP_MAC1 (1 << 20) #define SCU_CLKSTOP_MAC2 (1 << 21) +#define SCU_CLKSTOP_SDCLK (1 << 27) #define SCU_D2PLL_EXT1_OFF (1 << 0) #define SCU_D2PLL_EXT1_BYPASS (1 << 1) diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c index dbee13a..9249cf9 100644 --- a/drivers/clk/aspeed/clk_ast2500.c +++ b/drivers/clk/aspeed/clk_ast2500.c @@ -143,6 +143,17 @@ static ulong ast2500_clk_get_rate(struct clk *clk) rate = rate / apb_div; } break; + case BCLK_SDCLK: + { + ulong apb_div = 4 + 4 * ((readl(>scu->clk_sel1) + & SCU_SDCLK_DIV_MASK) +>> SCU_SDCLK_DIV_SHIFT); + rate = ast2500_get_hpll_rate(clkin, +readl(> + scu->h_pll_param)); + rate = rate / apb_div; + } + break; case PCLK_UART1: rate = ast2500_get_uart_clk_rate(priv->scu, 1); break; @@ -436,6 +447,22 @@ static int ast2500_clk_enable(struct clk *clk) struct ast2500_clk_priv *priv = dev_get_priv(clk->dev); switch (clk->id) { + case BCLK_SDCLK: + if (readl(>scu->clk_stop_ctrl1) & SCU_CLKSTOP_SDCLK) { + ast_scu_unlock(priv->scu); + + setbits_le32(>scu->sysreset_ctrl1, +SCU_SYSRESET_SDIO); + udelay(100); + clrbits_le32(>scu->clk_stop_ctrl1, +SCU_CLKSTOP_SDCLK); + mdelay(10); + clrbits_le32(>scu->sysreset_ctrl1, +SCU_SYSRESET_SDIO); + + ast_scu_lock(priv->scu); + } + break; /* * For MAC clocks the clock rate is * configured based on whether RGMII or RMII mode has been selected diff --git a/drivers/pinctrl/aspeed/pinctrl_ast2500.c b/drivers/pinctrl/aspeed/pinctrl_ast2500.c index ed333b9..a6e9c0d 100644 --- a/drivers/pinctrl/aspeed/pinctrl_ast2500.c +++ b/drivers/pinctrl/aspeed/pinctrl_ast2500.c @@ -58,6 +58,8 @@ static const struct ast2500_group_config ast2500_groups[] = { { "MDIO1", 3, (1 << 31) | (1 << 30) }, { "MAC2LINK", 1, (1 << 1) }, { "MDIO2", 5, (1 << 2) }, + { "SD1", 5, (1 << 0) }, + { "SD2", 5, (1 << 1) }, }; static int ast2500_pinctrl_get_groups_count(struct udevice *dev) -- 1.8.3.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
Re: [U-Boot] [PATCH v2 2/4] mmc: Add Aspeed SD controller driver
On 8/14/19 10:18 AM, Cédric Le Goater wrote: On 13/08/2019 21:31, Eddie James wrote: Add support for the Aspeed SD host controller engine. It looks correct and simple enough. Some comments below. Signed-off-by: Eddie James --- drivers/mmc/Kconfig| 11 +++ drivers/mmc/Makefile | 1 + drivers/mmc/aspeed_sdhci.c | 78 ++ 3 files changed, 90 insertions(+) create mode 100644 drivers/mmc/aspeed_sdhci.c diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index c6812f6..536f66a 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -421,6 +421,17 @@ config SPL_MMC_SDHCI_ADMA This enables support for the ADMA (Advanced DMA) defined in the SD Host Controller Standard Specification Version 3.00 in SPL. +config MMC_SDHCI_ASPEED + bool "Aspeed SDHCI controller" + depends on ARCH_ASPEED + depends on DM_MMC + depends on MMC_SDHCI + help + Enables support for the Aspeed SDHCI 2.0 controller present on Aspeed + SoCs. This device is compatible with SD 3.0 and/or MMC 4.3 + specifications. On the AST2600, the device is also compatible with + MMC 5.1 and eMMC 3.0. + config MMC_SDHCI_ATMEL bool "Atmel SDHCI controller support" depends on ARCH_AT91 diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 6cc018b..5594195 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o # SDHCI obj-$(CONFIG_MMC_SDHCI) += sdhci.o +obj-$(CONFIG_MMC_SDHCI_ASPEED) += aspeed_sdhci.o obj-$(CONFIG_MMC_SDHCI_ATMEL) += atmel_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCM2835) += bcm2835_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCMSTB)+= bcmstb_sdhci.o diff --git a/drivers/mmc/aspeed_sdhci.c b/drivers/mmc/aspeed_sdhci.c new file mode 100644 index 000..c292c42 --- /dev/null +++ b/drivers/mmc/aspeed_sdhci.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 IBM Corp. + * Eddie James + */ + +#include +#include +#include +#include +#include + +struct aspeed_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +static int aspeed_sdhci_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct aspeed_sdhci_plat *plat = dev_get_platdata(dev); + struct sdhci_host *host = dev_get_priv(dev); + u32 max_clk; + struct clk clk; + int ret; + + ret = clk_get_by_index(dev, 0, ); + if (ret) + return ret; + + ret = clk_enable(); + if (ret) + return ret; Don't we need to release the clock below in case of error ? Yes. + host->name = dev->name; + host->ioaddr = (void *)devfdt_get_addr(dev); + + max_clk = clk_get_rate(); + if (!max_clk) may be use IS_ERR_VALUE(max_clk) and return max_clk Yep, good idea. Thanks for the quick review! Eddie + return -EINVAL; + + host->max_clk = max_clk; + host->mmc = >mmc; + host->mmc->dev = dev; + host->mmc->priv = host; + upriv->mmc = host->mmc; + + ret = sdhci_setup_cfg(>cfg, host, 0, 0); + if (ret) + return ret; + + return sdhci_probe(dev); +} + +static int aspeed_sdhci_bind(struct udevice *dev) +{ + struct aspeed_sdhci_plat *plat = dev_get_platdata(dev); + + return sdhci_bind(dev, >mmc, >cfg); +} + +static const struct udevice_id aspeed_sdhci_ids[] = { + { .compatible = "aspeed,ast2400-sdhci" }, + { .compatible = "aspeed,ast2500-sdhci" }, + { .compatible = "aspeed,ast2600-sdhci" }, + { } +}; + +U_BOOT_DRIVER(aspeed_sdhci_drv) = { + .name = "aspeed_sdhci", + .id = UCLASS_MMC, + .of_match = aspeed_sdhci_ids, + .ops= _ops, + .bind = aspeed_sdhci_bind, + .probe = aspeed_sdhci_probe, + .priv_auto_alloc_size = sizeof(struct sdhci_host), + .platdata_auto_alloc_size = sizeof(struct aspeed_sdhci_plat), +}; ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
Re: [U-Boot] [PATCH v2 3/4] aspeed: Support SD controller on the ast2500 board
On 8/14/19 10:23 AM, Cédric Le Goater wrote: On 13/08/2019 21:31, Eddie James wrote: Initialize the MMC subsystem on the ast2500 board. Compile MMC and the Aspeed SD controller on the ast2500 EVB. Signed-off-by: Eddie James --- arch/arm/include/asm/gpio.h | 3 ++- arch/arm/mach-aspeed/ast2500-board.c | 3 +++ configs/evb-ast2500_defconfig| 6 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h index 370031f..38a5922 100644 --- a/arch/arm/include/asm/gpio.h +++ b/arch/arm/include/asm/gpio.h @@ -1,6 +1,7 @@ #if !defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARCH_STI) && \ !defined(CONFIG_ARCH_K3) && !defined(CONFIG_ARCH_BCM6858) && \ - !defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) + !defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) && \ + !defined(CONFIG_ARCH_ASPEED) #include #endif #include diff --git a/arch/arm/mach-aspeed/ast2500-board.c b/arch/arm/mach-aspeed/ast2500-board.c index e7edd54..52a4e05 100644 --- a/arch/arm/mach-aspeed/ast2500-board.c +++ b/arch/arm/mach-aspeed/ast2500-board.c @@ -4,6 +4,7 @@ */ #include #include +#include #include #include #include @@ -55,6 +56,8 @@ int board_init(void) { gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; + mmc_initialize(gd->bd); + isn't that called automatically by board_init_r() already ? You are correct, I will drop this. Thanks, Eddie C. return 0; } diff --git a/configs/evb-ast2500_defconfig b/configs/evb-ast2500_defconfig index 59d41cb..bfa6b32 100644 --- a/configs/evb-ast2500_defconfig +++ b/configs/evb-ast2500_defconfig @@ -16,6 +16,7 @@ CONFIG_HUSH_PARSER=y CONFIG_CMD_I2C=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y +CONFIG_CMD_MMC=y CONFIG_CMD_PING=y CONFIG_DEFAULT_DEVICE_TREE="ast2500-evb" CONFIG_NET_RANDOM_ETHADDR=y @@ -36,3 +37,8 @@ CONFIG_SYS_NS16550=y CONFIG_SYSRESET=y CONFIG_TIMER=y CONFIG_WDT=y +CONFIG_MMC=y +CONFIG_DM_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_ASPEED=y +CONFIG_MMC_VERBOSE=y ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v3 4/4] ARM: dts: ast2500: Add SDHCI nodes
Add nodes for the Aspeed SD controllers with their necessary properties. Reviewed-by: Cédric Le Goater Signed-off-by: Eddie James --- arch/arm/dts/ast2500-evb.dts | 14 ++ arch/arm/dts/ast2500-u-boot.dtsi | 16 2 files changed, 30 insertions(+) diff --git a/arch/arm/dts/ast2500-evb.dts b/arch/arm/dts/ast2500-evb.dts index ebf44fd..4796ed4 100644 --- a/arch/arm/dts/ast2500-evb.dts +++ b/arch/arm/dts/ast2500-evb.dts @@ -59,3 +59,17 @@ pinctrl-names = "default"; pinctrl-0 = <_mac2link_default _mdio2_default>; }; + + { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <_sd1_default>; +}; + + { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <_sd2_default>; +}; diff --git a/arch/arm/dts/ast2500-u-boot.dtsi b/arch/arm/dts/ast2500-u-boot.dtsi index 7f80bad..8ac4215 100644 --- a/arch/arm/dts/ast2500-u-boot.dtsi +++ b/arch/arm/dts/ast2500-u-boot.dtsi @@ -34,6 +34,22 @@ apb { u-boot,dm-pre-reloc; + + sdhci0: sdhci@1e740100 { + compatible = "aspeed,ast2500-sdhci"; + reg = <0x1e740100>; + #reset-cells = <1>; + clocks = < BCLK_SDCLK>; + resets = < AST_RESET_SDIO>; + }; + + sdhci1: sdhci@1e740200 { + compatible = "aspeed,ast2500-sdhci"; + reg = <0x1e740200>; + #reset-cells = <1>; + clocks = < BCLK_SDCLK>; + resets = < AST_RESET_SDIO>; + }; }; }; -- 1.8.3.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v3 2/4] mmc: Add Aspeed SD controller driver
Add support for the Aspeed SD host controller engine. Signed-off-by: Eddie James --- arch/arm/include/asm/gpio.h | 3 +- drivers/mmc/Kconfig | 11 ++ drivers/mmc/Makefile| 1 + drivers/mmc/aspeed_sdhci.c | 90 + 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/aspeed_sdhci.c diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h index 370031f..38a5922 100644 --- a/arch/arm/include/asm/gpio.h +++ b/arch/arm/include/asm/gpio.h @@ -1,6 +1,7 @@ #if !defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARCH_STI) && \ !defined(CONFIG_ARCH_K3) && !defined(CONFIG_ARCH_BCM6858) && \ - !defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) + !defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) && \ + !defined(CONFIG_ARCH_ASPEED) #include #endif #include diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index c6812f6..536f66a 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -421,6 +421,17 @@ config SPL_MMC_SDHCI_ADMA This enables support for the ADMA (Advanced DMA) defined in the SD Host Controller Standard Specification Version 3.00 in SPL. +config MMC_SDHCI_ASPEED + bool "Aspeed SDHCI controller" + depends on ARCH_ASPEED + depends on DM_MMC + depends on MMC_SDHCI + help + Enables support for the Aspeed SDHCI 2.0 controller present on Aspeed + SoCs. This device is compatible with SD 3.0 and/or MMC 4.3 + specifications. On the AST2600, the device is also compatible with + MMC 5.1 and eMMC 3.0. + config MMC_SDHCI_ATMEL bool "Atmel SDHCI controller support" depends on ARCH_AT91 diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 6cc018b..5594195 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o # SDHCI obj-$(CONFIG_MMC_SDHCI)+= sdhci.o +obj-$(CONFIG_MMC_SDHCI_ASPEED) += aspeed_sdhci.o obj-$(CONFIG_MMC_SDHCI_ATMEL) += atmel_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCM2835)+= bcm2835_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCMSTB) += bcmstb_sdhci.o diff --git a/drivers/mmc/aspeed_sdhci.c b/drivers/mmc/aspeed_sdhci.c new file mode 100644 index 000..1321ec3 --- /dev/null +++ b/drivers/mmc/aspeed_sdhci.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 IBM Corp. + * Eddie James + */ + +#include +#include +#include +#include +#include + +struct aspeed_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +static int aspeed_sdhci_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct aspeed_sdhci_plat *plat = dev_get_platdata(dev); + struct sdhci_host *host = dev_get_priv(dev); + u32 max_clk; + struct clk clk; + int ret; + + ret = clk_get_by_index(dev, 0, ); + if (ret) + return ret; + + ret = clk_enable(); + if (ret) + goto free; + + host->name = dev->name; + host->ioaddr = (void *)devfdt_get_addr(dev); + + max_clk = clk_get_rate(); + if (IS_ERR_VALUE(max_clk)) { + ret = max_clk; + goto err; + } + + host->max_clk = max_clk; + host->mmc = >mmc; + host->mmc->dev = dev; + host->mmc->priv = host; + upriv->mmc = host->mmc; + + ret = sdhci_setup_cfg(>cfg, host, 0, 0); + if (ret) + goto err; + + ret = sdhci_probe(dev); + if (ret) + goto err; + + return 0; + +err: + clk_disable(); +free: + clk_free(); + return ret; +} + +static int aspeed_sdhci_bind(struct udevice *dev) +{ + struct aspeed_sdhci_plat *plat = dev_get_platdata(dev); + + return sdhci_bind(dev, >mmc, >cfg); +} + +static const struct udevice_id aspeed_sdhci_ids[] = { + { .compatible = "aspeed,ast2400-sdhci" }, + { .compatible = "aspeed,ast2500-sdhci" }, + { .compatible = "aspeed,ast2600-sdhci" }, + { } +}; + +U_BOOT_DRIVER(aspeed_sdhci_drv) = { + .name = "aspeed_sdhci", + .id = UCLASS_MMC, + .of_match = aspeed_sdhci_ids, + .ops= _ops, + .bind = aspeed_sdhci_bind, + .probe = aspeed_sdhci_probe, + .priv_auto_alloc_size = sizeof(struct sdhci_host), + .platdata_auto_alloc_size = sizeof(struct aspeed_sdhci_plat), +}; -- 1.8.3.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH] ARM: aspeed: Add SD host controller driver
Add support for the Aspeed SD host controller engine. This involves adding an MMC SDHCI driver and various additions to the clock and reset drivers for Aspeed chips. Signed-off-by: Eddie James --- arch/arm/include/asm/arch-aspeed/scu_ast2500.h | 3 + arch/arm/include/asm/gpio.h| 3 +- arch/arm/mach-aspeed/ast2500-board.c | 3 + drivers/clk/aspeed/clk_ast2500.c | 27 + drivers/mmc/Kconfig| 11 drivers/mmc/Makefile | 1 + drivers/mmc/aspeed_sdhci.c | 78 ++ drivers/pinctrl/aspeed/pinctrl_ast2500.c | 2 + 8 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/aspeed_sdhci.c diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h index 4988ced..8db4901 100644 --- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h +++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h @@ -22,6 +22,8 @@ #define SCU_MPLL_POST_MASK (0x3f << SCU_MPLL_POST_SHIFT) #define SCU_PCLK_DIV_SHIFT 23 #define SCU_PCLK_DIV_MASK (7 << SCU_PCLK_DIV_SHIFT) +#define SCU_SDCLK_DIV_SHIFT12 +#define SCU_SDCLK_DIV_MASK (7 << SCU_SDCLK_DIV_SHIFT) #define SCU_HPLL_DENUM_SHIFT 0 #define SCU_HPLL_DENUM_MASK0x1f #define SCU_HPLL_NUM_SHIFT 5 @@ -107,6 +109,7 @@ #define SCU_CLKSTOP_MAC1 (1 << 20) #define SCU_CLKSTOP_MAC2 (1 << 21) +#define SCU_CLKSTOP_SDCLK (1 << 27) #define SCU_D2PLL_EXT1_OFF (1 << 0) #define SCU_D2PLL_EXT1_BYPASS (1 << 1) diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h index 370031f..38a5922 100644 --- a/arch/arm/include/asm/gpio.h +++ b/arch/arm/include/asm/gpio.h @@ -1,6 +1,7 @@ #if !defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARCH_STI) && \ !defined(CONFIG_ARCH_K3) && !defined(CONFIG_ARCH_BCM6858) && \ - !defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) + !defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) && \ + !defined(CONFIG_ARCH_ASPEED) #include #endif #include diff --git a/arch/arm/mach-aspeed/ast2500-board.c b/arch/arm/mach-aspeed/ast2500-board.c index e7edd54..52a4e05 100644 --- a/arch/arm/mach-aspeed/ast2500-board.c +++ b/arch/arm/mach-aspeed/ast2500-board.c @@ -4,6 +4,7 @@ */ #include #include +#include #include #include #include @@ -55,6 +56,8 @@ int board_init(void) { gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; + mmc_initialize(gd->bd); + return 0; } diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c index dbee13a..9249cf9 100644 --- a/drivers/clk/aspeed/clk_ast2500.c +++ b/drivers/clk/aspeed/clk_ast2500.c @@ -143,6 +143,17 @@ static ulong ast2500_clk_get_rate(struct clk *clk) rate = rate / apb_div; } break; + case BCLK_SDCLK: + { + ulong apb_div = 4 + 4 * ((readl(>scu->clk_sel1) + & SCU_SDCLK_DIV_MASK) +>> SCU_SDCLK_DIV_SHIFT); + rate = ast2500_get_hpll_rate(clkin, +readl(> + scu->h_pll_param)); + rate = rate / apb_div; + } + break; case PCLK_UART1: rate = ast2500_get_uart_clk_rate(priv->scu, 1); break; @@ -436,6 +447,22 @@ static int ast2500_clk_enable(struct clk *clk) struct ast2500_clk_priv *priv = dev_get_priv(clk->dev); switch (clk->id) { + case BCLK_SDCLK: + if (readl(>scu->clk_stop_ctrl1) & SCU_CLKSTOP_SDCLK) { + ast_scu_unlock(priv->scu); + + setbits_le32(>scu->sysreset_ctrl1, +SCU_SYSRESET_SDIO); + udelay(100); + clrbits_le32(>scu->clk_stop_ctrl1, +SCU_CLKSTOP_SDCLK); + mdelay(10); + clrbits_le32(>scu->sysreset_ctrl1, +SCU_SYSRESET_SDIO); + + ast_scu_lock(priv->scu); + } + break; /* * For MAC clocks the clock rate is * configured based on whether RGMII or RMII mode has been selected diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index c6812f6..536f66a 100644 --- a/drivers/mmc/Kconfig +++ b/
[U-Boot] [PATCH v4 2/4] mmc: Add Aspeed SD controller driver
Add support for the Aspeed SD host controller engine. Signed-off-by: Eddie James Reviewed-by: Cédric Le Goater --- Changes since v3: - Rebase on master arch/arm/include/asm/gpio.h | 3 +- drivers/mmc/Kconfig | 11 ++ drivers/mmc/Makefile| 1 + drivers/mmc/aspeed_sdhci.c | 90 + 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/aspeed_sdhci.c diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h index b946105..6ff5f42 100644 --- a/arch/arm/include/asm/gpio.h +++ b/arch/arm/include/asm/gpio.h @@ -2,7 +2,8 @@ !defined(CONFIG_ARCH_K3) && !defined(CONFIG_ARCH_BCM6858) && \ !defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) && \ !defined(CONFIG_ARCH_LX2160A) && !defined(CONFIG_ARCH_LS1028A) && \ - !defined(CONFIG_ARCH_LS2080A) && !defined(CONFIG_ARCH_LS1088A) + !defined(CONFIG_ARCH_LS2080A) && !defined(CONFIG_ARCH_LS1088A) && \ + !defined(CONFIG_ARCH_ASPEED) #include #endif #include diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 0ccb1ea..8fb2bfa 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -421,6 +421,17 @@ config SPL_MMC_SDHCI_ADMA This enables support for the ADMA (Advanced DMA) defined in the SD Host Controller Standard Specification Version 3.00 in SPL. +config MMC_SDHCI_ASPEED + bool "Aspeed SDHCI controller" + depends on ARCH_ASPEED + depends on DM_MMC + depends on MMC_SDHCI + help + Enables support for the Aspeed SDHCI 2.0 controller present on Aspeed + SoCs. This device is compatible with SD 3.0 and/or MMC 4.3 + specifications. On the AST2600, the device is also compatible with + MMC 5.1 and eMMC 3.0. + config MMC_SDHCI_ATMEL bool "Atmel SDHCI controller support" depends on ARCH_AT91 diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 6cc018b..5594195 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o # SDHCI obj-$(CONFIG_MMC_SDHCI)+= sdhci.o +obj-$(CONFIG_MMC_SDHCI_ASPEED) += aspeed_sdhci.o obj-$(CONFIG_MMC_SDHCI_ATMEL) += atmel_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCM2835)+= bcm2835_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCMSTB) += bcmstb_sdhci.o diff --git a/drivers/mmc/aspeed_sdhci.c b/drivers/mmc/aspeed_sdhci.c new file mode 100644 index 000..1321ec3 --- /dev/null +++ b/drivers/mmc/aspeed_sdhci.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 IBM Corp. + * Eddie James + */ + +#include +#include +#include +#include +#include + +struct aspeed_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +static int aspeed_sdhci_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct aspeed_sdhci_plat *plat = dev_get_platdata(dev); + struct sdhci_host *host = dev_get_priv(dev); + u32 max_clk; + struct clk clk; + int ret; + + ret = clk_get_by_index(dev, 0, ); + if (ret) + return ret; + + ret = clk_enable(); + if (ret) + goto free; + + host->name = dev->name; + host->ioaddr = (void *)devfdt_get_addr(dev); + + max_clk = clk_get_rate(); + if (IS_ERR_VALUE(max_clk)) { + ret = max_clk; + goto err; + } + + host->max_clk = max_clk; + host->mmc = >mmc; + host->mmc->dev = dev; + host->mmc->priv = host; + upriv->mmc = host->mmc; + + ret = sdhci_setup_cfg(>cfg, host, 0, 0); + if (ret) + goto err; + + ret = sdhci_probe(dev); + if (ret) + goto err; + + return 0; + +err: + clk_disable(); +free: + clk_free(); + return ret; +} + +static int aspeed_sdhci_bind(struct udevice *dev) +{ + struct aspeed_sdhci_plat *plat = dev_get_platdata(dev); + + return sdhci_bind(dev, >mmc, >cfg); +} + +static const struct udevice_id aspeed_sdhci_ids[] = { + { .compatible = "aspeed,ast2400-sdhci" }, + { .compatible = "aspeed,ast2500-sdhci" }, + { .compatible = "aspeed,ast2600-sdhci" }, + { } +}; + +U_BOOT_DRIVER(aspeed_sdhci_drv) = { + .name = "aspeed_sdhci", + .id = UCLASS_MMC, + .of_match = aspeed_sdhci_ids, + .ops= _ops, + .bind = aspeed_sdhci_bind, + .probe = aspeed_sdhci_probe, + .priv_auto_alloc_size = sizeof(struct sdhci_host), + .platdata_auto_alloc_size = sizeof(struct aspeed_sdhci_plat), +}; -- 1.8.3.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
Re: [U-Boot] [PATCH v3 2/4] mmc: Add Aspeed SD controller driver
On 8/27/19 2:34 AM, Peng Fan wrote: Hi Eddie, Subject: [PATCH v3 2/4] mmc: Add Aspeed SD controller driver This patch could not be applied to latest tree, could you please check? Sorry I was a little behind master. I just sent this patch rebased. Thanks, Eddie Thanks, Peng. Add support for the Aspeed SD host controller engine. Signed-off-by: Eddie James --- arch/arm/include/asm/gpio.h | 3 +- drivers/mmc/Kconfig | 11 ++ drivers/mmc/Makefile| 1 + drivers/mmc/aspeed_sdhci.c | 90 + 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/aspeed_sdhci.c diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h index 370031f..38a5922 100644 --- a/arch/arm/include/asm/gpio.h +++ b/arch/arm/include/asm/gpio.h @@ -1,6 +1,7 @@ #if !defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARCH_STI) && \ !defined(CONFIG_ARCH_K3) && !defined(CONFIG_ARCH_BCM6858) && \ - !defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) + !defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) && \ + !defined(CONFIG_ARCH_ASPEED) #include #endif #include diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index c6812f6..536f66a 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -421,6 +421,17 @@ config SPL_MMC_SDHCI_ADMA This enables support for the ADMA (Advanced DMA) defined in the SD Host Controller Standard Specification Version 3.00 in SPL. +config MMC_SDHCI_ASPEED + bool "Aspeed SDHCI controller" + depends on ARCH_ASPEED + depends on DM_MMC + depends on MMC_SDHCI + help + Enables support for the Aspeed SDHCI 2.0 controller present on Aspeed + SoCs. This device is compatible with SD 3.0 and/or MMC 4.3 + specifications. On the AST2600, the device is also compatible with + MMC 5.1 and eMMC 3.0. + config MMC_SDHCI_ATMEL bool "Atmel SDHCI controller support" depends on ARCH_AT91 diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 6cc018b..5594195 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o # SDHCI obj-$(CONFIG_MMC_SDHCI) += sdhci.o +obj-$(CONFIG_MMC_SDHCI_ASPEED) += aspeed_sdhci.o obj-$(CONFIG_MMC_SDHCI_ATMEL) += atmel_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCM2835) += bcm2835_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCMSTB)+= bcmstb_sdhci.o diff --git a/drivers/mmc/aspeed_sdhci.c b/drivers/mmc/aspeed_sdhci.c new file mode 100644 index 000..1321ec3 --- /dev/null +++ b/drivers/mmc/aspeed_sdhci.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 IBM Corp. + * Eddie James + */ + +#include +#include +#include +#include +#include + +struct aspeed_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +static int aspeed_sdhci_probe(struct udevice *dev) { + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct aspeed_sdhci_plat *plat = dev_get_platdata(dev); + struct sdhci_host *host = dev_get_priv(dev); + u32 max_clk; + struct clk clk; + int ret; + + ret = clk_get_by_index(dev, 0, ); + if (ret) + return ret; + + ret = clk_enable(); + if (ret) + goto free; + + host->name = dev->name; + host->ioaddr = (void *)devfdt_get_addr(dev); + + max_clk = clk_get_rate(); + if (IS_ERR_VALUE(max_clk)) { + ret = max_clk; + goto err; + } + + host->max_clk = max_clk; + host->mmc = >mmc; + host->mmc->dev = dev; + host->mmc->priv = host; + upriv->mmc = host->mmc; + + ret = sdhci_setup_cfg(>cfg, host, 0, 0); + if (ret) + goto err; + + ret = sdhci_probe(dev); + if (ret) + goto err; + + return 0; + +err: + clk_disable(); +free: + clk_free(); + return ret; +} + +static int aspeed_sdhci_bind(struct udevice *dev) { + struct aspeed_sdhci_plat *plat = dev_get_platdata(dev); + + return sdhci_bind(dev, >mmc, >cfg); } + +static const struct udevice_id aspeed_sdhci_ids[] = { + { .compatible = "aspeed,ast2400-sdhci" }, + { .compatible = "aspeed,ast2500-sdhci" }, + { .compatible = "aspeed,ast2600-sdhci" }, + { } +}; + +U_BOOT_DRIVER(aspeed_sdhci_drv) = { + .name = "aspeed_sdhci", + .id = UCLASS_MMC, + .of_match = aspeed_sdhci_ids, + .ops= _ops, + .bind = aspeed_sdhci_bind, + .probe = aspeed_sdhci_probe, + .priv_auto_alloc_size =
Re: [PATCH] gpio: Enable hogging support in SPL
On 2/4/22 09:24, Simon Glass wrote: Hi Eddie, On Thu, 3 Feb 2022 at 15:37, Eddie James wrote: Use the CONFIG macros to conditionally build the GPIO hogging support in either the SPL or U-Boot, or both, depending on the configuration. Also call the GPIO hog probe function in the common SPL board initialization as an equivalent to adding it to the U-Boot init sequence functions. Signed-off-by: Eddie James --- common/spl/spl.c | 7 +++ drivers/gpio/Kconfig | 10 ++ drivers/gpio/gpio-uclass.c | 10 ++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/common/spl/spl.c b/common/spl/spl.c index 884102bdea..f667908eec 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -20,6 +20,9 @@ #include #include #include +#if defined(CONFIG_SPL_GPIO_HOG) Can you drop this ifdef? Sure. +#include +#endif #include #include #include @@ -739,6 +742,10 @@ void board_init_r(gd_t *dummy1, ulong dummy2) } } +#if defined(CONFIG_SPL_GPIO_HOG) + gpio_hog_probe_all(); +#endif if (CONFIG_IS_ENABLED(GPIO_HOG)) Ack. ... + #if CONFIG_IS_ENABLED(BOARD_INIT) spl_board_init(); #endif diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 305a2dc563..4da2bdc10d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -57,6 +57,16 @@ config GPIO_HOG is a mechanism providing automatic GPIO request and config- uration as part of the gpio-controller's driver probe function. +config SPL_GPIO_HOG + bool "Enable GPIO hog support in SPL" + depends on SPL_GPIO_SUPPORT Should it depend on GPIO_HOG? I'm not sure, just a question No, this way the gpio hog support can be configured for either SPL or U-Boot or both. They are the same option just in the different builds. Thanks for the review, Eddie + default n + help + Enable gpio hog support in SPL + The GPIO chip may contain GPIO hog definitions. GPIO hogging + is a mechanism providing automatic GPIO request and config- + uration as part of the gpio-controller's driver probe function. + config DM_GPIO_LOOKUP_LABEL bool "Enable searching for gpio labelnames" depends on DM_GPIO diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 125ae53d61..bebba620c9 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -1432,9 +1432,6 @@ void devm_gpiod_put(struct udevice *dev, struct gpio_desc *desc) static int gpio_post_bind(struct udevice *dev) { - struct udevice *child; - ofnode node; - #if defined(CONFIG_NEEDS_MANUAL_RELOC) struct dm_gpio_ops *ops = (struct dm_gpio_ops *)device_get_ops(dev); static int reloc_done; @@ -1465,7 +1462,11 @@ static int gpio_post_bind(struct udevice *dev) } #endif - if (CONFIG_IS_ENABLED(OF_REAL) && IS_ENABLED(CONFIG_GPIO_HOG)) { +#if CONFIG_IS_ENABLED(GPIO_HOG) + { + struct udevice *child; + ofnode node; + dev_for_each_subnode(node, dev) { if (ofnode_read_bool(node, "gpio-hog")) { const char *name = ofnode_get_name(node); @@ -1480,6 +1481,7 @@ static int gpio_post_bind(struct udevice *dev) } } } +#endif return 0; } -- 2.27.0
[PATCH v3] gpio: Enable hogging support in SPL
Use the CONFIG macros to conditionally build the GPIO hogging support in either the SPL or U-Boot, or both, depending on the configuration. Also call the GPIO hog probe function in the common SPL board initialization as an equivalent to adding it to the U-Boot init sequence functions. Signed-off-by: Eddie James --- Changes since v2: - change #if to if() in gpio_post_bind Changes since v1: - remove #if guards around gpio include - change #if to if() in spl board_init_r common/spl/spl.c | 4 drivers/gpio/Kconfig | 10 ++ drivers/gpio/gpio-uclass.c | 8 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/common/spl/spl.c b/common/spl/spl.c index 884102bdea..36115e674d 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -739,6 +740,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2) } } + if (CONFIG_IS_ENABLED(GPIO_HOG)) + gpio_hog_probe_all(); + #if CONFIG_IS_ENABLED(BOARD_INIT) spl_board_init(); #endif diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 305a2dc563..4da2bdc10d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -57,6 +57,16 @@ config GPIO_HOG is a mechanism providing automatic GPIO request and config- uration as part of the gpio-controller's driver probe function. +config SPL_GPIO_HOG + bool "Enable GPIO hog support in SPL" + depends on SPL_GPIO_SUPPORT + default n + help + Enable gpio hog support in SPL + The GPIO chip may contain GPIO hog definitions. GPIO hogging + is a mechanism providing automatic GPIO request and config- + uration as part of the gpio-controller's driver probe function. + config DM_GPIO_LOOKUP_LABEL bool "Enable searching for gpio labelnames" depends on DM_GPIO diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 125ae53d61..9075c7235d 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -1432,9 +1432,6 @@ void devm_gpiod_put(struct udevice *dev, struct gpio_desc *desc) static int gpio_post_bind(struct udevice *dev) { - struct udevice *child; - ofnode node; - #if defined(CONFIG_NEEDS_MANUAL_RELOC) struct dm_gpio_ops *ops = (struct dm_gpio_ops *)device_get_ops(dev); static int reloc_done; @@ -1465,7 +1462,10 @@ static int gpio_post_bind(struct udevice *dev) } #endif - if (CONFIG_IS_ENABLED(OF_REAL) && IS_ENABLED(CONFIG_GPIO_HOG)) { + if (CONFIG_IS_ENABLED(GPIO_HOG)) { + struct udevice *child; + ofnode node; + dev_for_each_subnode(node, dev) { if (ofnode_read_bool(node, "gpio-hog")) { const char *name = ofnode_get_name(node); -- 2.27.0
[PATCH v2] gpio: Enable hogging support in SPL
Use the CONFIG macros to conditionally build the GPIO hogging support in either the SPL or U-Boot, or both, depending on the configuration. Also call the GPIO hog probe function in the common SPL board initialization as an equivalent to adding it to the U-Boot init sequence functions. Signed-off-by: Eddie James --- common/spl/spl.c | 4 drivers/gpio/Kconfig | 10 ++ drivers/gpio/gpio-uclass.c | 10 ++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/common/spl/spl.c b/common/spl/spl.c index 884102bdea..36115e674d 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -739,6 +740,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2) } } + if (CONFIG_IS_ENABLED(GPIO_HOG)) + gpio_hog_probe_all(); + #if CONFIG_IS_ENABLED(BOARD_INIT) spl_board_init(); #endif diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 305a2dc563..4da2bdc10d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -57,6 +57,16 @@ config GPIO_HOG is a mechanism providing automatic GPIO request and config- uration as part of the gpio-controller's driver probe function. +config SPL_GPIO_HOG + bool "Enable GPIO hog support in SPL" + depends on SPL_GPIO_SUPPORT + default n + help + Enable gpio hog support in SPL + The GPIO chip may contain GPIO hog definitions. GPIO hogging + is a mechanism providing automatic GPIO request and config- + uration as part of the gpio-controller's driver probe function. + config DM_GPIO_LOOKUP_LABEL bool "Enable searching for gpio labelnames" depends on DM_GPIO diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 125ae53d61..bebba620c9 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -1432,9 +1432,6 @@ void devm_gpiod_put(struct udevice *dev, struct gpio_desc *desc) static int gpio_post_bind(struct udevice *dev) { - struct udevice *child; - ofnode node; - #if defined(CONFIG_NEEDS_MANUAL_RELOC) struct dm_gpio_ops *ops = (struct dm_gpio_ops *)device_get_ops(dev); static int reloc_done; @@ -1465,7 +1462,11 @@ static int gpio_post_bind(struct udevice *dev) } #endif - if (CONFIG_IS_ENABLED(OF_REAL) && IS_ENABLED(CONFIG_GPIO_HOG)) { +#if CONFIG_IS_ENABLED(GPIO_HOG) + { + struct udevice *child; + ofnode node; + dev_for_each_subnode(node, dev) { if (ofnode_read_bool(node, "gpio-hog")) { const char *name = ofnode_get_name(node); @@ -1480,6 +1481,7 @@ static int gpio_post_bind(struct udevice *dev) } } } +#endif return 0; } -- 2.27.0
Re: [PATCH v14 4/8] bootm: Support boot measurement
On 10/25/23 07:41, Ilias Apalodimas wrote: On Tue, 24 Oct 2023 at 18:44, Eddie James wrote: Add a configuration option to measure the boot through the bootm function. Add the measurement state to the booti and bootz paths as well. Signed-off-by: Eddie James Reviewed-by: Simon Glass --- Changes since v8: - Added a configuration option to select to ignore any existing event log. This would only be selected for systems that know that U-Boot is the first stage bootloader. This is necessary because the reserved memory region may persist through resets and so U-Boot attempts to append to the previous boot's log. Changes since v6: - Added comment for bootm_measure - Fixed line length in bootm_measure boot/Kconfig| 32 + boot/bootm.c| 74 + cmd/booti.c | 1 + cmd/bootm.c | 2 ++ cmd/bootz.c | 1 + include/bootm.h | 11 include/image.h | 1 + 7 files changed, 122 insertions(+) diff --git a/boot/Kconfig b/boot/Kconfig index a01e6cb8aa..abbc72f4cf 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -685,6 +685,38 @@ config LEGACY_IMAGE_FORMAT loaded. If a board needs the legacy image format support in this case, enable it here. +config MEASURED_BOOT + bool "Measure boot images and configuration to TPM and event log" + depends on HASH && TPM_V2 I know Simon reviewed this already, but don't we need to add !EFI here? UEFI already supports measurements via the TCG protocol implementation. But since EFI is 'default y' nowadays anyone minds if I change the help & bool messages during merge? Something along the lines of bool "Measure boot images and configuration to TPM and event log when booting without EFI" Oh right, yes, go ahead, that sounds good, thanks. Eddie [...] Thanks /Ilias
[PATCH v12 5/8] test: Add sandbox TPM boot measurement
Use the sandbox TPM driver to measure some boot images in a unit test case. Signed-off-by: Eddie James Reviewed-by: Simon Glass Acked-by: Ilias Apalodimas --- Changes since v5: - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT is enabled. arch/sandbox/dts/sandbox.dtsi | 13 +++ arch/sandbox/dts/test.dts | 13 +++ configs/sandbox_defconfig | 1 + include/test/suites.h | 1 + test/boot/Makefile| 1 + test/boot/measurement.c | 66 +++ test/cmd_ut.c | 4 +++ 7 files changed, 99 insertions(+) create mode 100644 test/boot/measurement.c diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index ff7e5584c5..241f397ba6 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -4,11 +4,23 @@ * and sandbox64 builds. */ +#include #include #define USB_CLASS_HUB 9 / { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman { }; @@ -342,6 +354,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; triangle { diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 9a863ea732..bb2ddd9bf2 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -9,6 +9,7 @@ /dts-v1/; +#include #include #include #include @@ -68,6 +69,17 @@ osd0 = "/osd"; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman: binman { }; @@ -1422,6 +1434,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; tpm { diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index d667cb9ae4..12c387a77e 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -349,3 +349,4 @@ CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y CONFIG_ARM_FFA_TRANSPORT=y +CONFIG_MEASURED_BOOT=y diff --git a/include/test/suites.h b/include/test/suites.h index 1c7dc65966..48ed549c13 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -45,6 +45,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); +int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/test/boot/Makefile b/test/boot/Makefile index 52947580ae..068522cb9e 100644 --- a/test/boot/Makefile +++ b/test/boot/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o obj-$(CONFIG_FIT) += image.o +obj-$(CONFIG_MEASURED_BOOT) += measurement.o obj-$(CONFIG_EXPO) += expo.o obj-$(CONFIG_CEDIT) += cedit.o diff --git a/test/boot/measurement.c b/test/boot/measurement.c new file mode 100644 index 00..9db2ed324c --- /dev/null +++ b/test/boot/measurement.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for measured boot functions + * + * Copyright 2023 IBM Corp. + * Written by Eddie James + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MEASUREMENT_TEST(_name, _flags)\ + UNIT_TEST(_name, _flags, measurement_test) + +static int measure(struct unit_test_state *uts) +{ + struct bootm_headers images; + const size_t size = 1024; + u8 *kernel; + u8 *initrd; + size_t i; + + kernel = malloc(size); + initrd = malloc(size); + + images.os.image_start = map_to_sysmem(kernel); + images.os.image_len = size; + + images.rd_start = map_to_sysmem(initrd); + images.rd_end = images.rd_start + size; + + images.ft_addr = malloc(size); + images.ft_len = size; + + env_set("bootargs", "measurement testing"); + + for (i = 0; i < size; ++i) { + kernel[i] = 0xf0 | (i & 0xf); + in
[PATCH v12 0/8] tpm: Support boot measurements
This series adds support for measuring the boot images more generically than the existing EFI support. Several EFI functions have been moved to the TPM layer. The series includes optional measurement from the bootm command. A new test case has been added for the bootm measurement to test the new path, and the sandbox TPM2 driver has been updated to support this use case. Changes since v11: - Rebase on next. Sorry for the delay (been on leave). Changes since v10: - Fix commit message on efi_loader change - Drop python test change - Squash armv7 fix from Ilias Changes since v9: - Rebase and add Ilias' fixes (thanks!) Changes since v8: - Fix a sandbox driver off-by-one error in checking the property type. - Fix log parsing again - any data corruption seen while replaying the event log was failing the entire measurement. - Added an option to ignore the existing log and a configuration option for systems to select that for the bootm measurement. This would only be selected for systems that know that U-Boot is the first stage bootloader. This is necessary because the reserved memory region may persist through resets and so U-Boot attempts to append to the previous boot's log. Changes since v7: - Change name of tcg2_init_log and add more documentation - Add a check, when parsing the event log header, to ensure that the previous stage bootloader used all the active PCRs. - Change name of tcg2_log_find_end - Fix the greater than or equal to check to exit the log parsing - Make sure log_position is 0 if there is any error discovering the log - Return errors parsing the log if the data is corrupt so that we don't end up with half a log Changes since v6: - Added comment for bootm_measure - Fixed line length in bootm_measure - Added Linaro copyright for all the EFI moved code - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to copy any discovered event log to the user's log if passed in. Changes since v5: - Re-ordered the patches to put the sandbox TPM driver patch second - Remove unused platform_get_eventlog in efi_tcg2.c - First look for tpm_event_log_* properties instead of linux,sml-* - Fix efi_tcg2.c compilation - Select SHA* configs - Remove the !SANDBOX dependency for EFI TCG2 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT is enabled Changes since v4: - Remove tcg2_measure_event function and check for NULL data in tcg2_measure_data - Use tpm_auto_startup - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function - Change PCR indexes for initrd and dtb - Drop u8 casting in measurement test - Use bullets in documentation Changes since v3: - Reordered headers - Refactored more of EFI code into common code Removed digest_info structure and instead used the common alg_to_mask and alg_to_len Improved event log parsing in common code to get it equivalent to EFI Common code now extends PCR if previous bootloader stage couldn't No need to allocate memory in the common code, so EFI copies the discovered buffer like it did before Rename efi measure_event function Changes since v2: - Add documentation. - Changed reserved memory address to the top of the RAM for sandbox dts. - Add measure state to booti and bootz. - Skip measurement for EFI images that should be measured Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions. - Add test case - Drop #ifdefs for bootm - Add devicetree measurement config option - Update sandbox TPM driver Eddie James (6): tpm: Fix spelling for tpmu_ha union tpm: sandbox: Update for needed TPM2 capabilities tpm: Support boot measurements bootm: Support boot measurement test: Add sandbox TPM boot measurement doc: Add measured boot documentation Ilias Apalodimas (2): efi_loader: fix EFI_ENTRY point on get_active_pcr_banks test: use a non system PCR for testing PCR extend arch/sandbox/dts/sandbox.dtsi | 13 + arch/sandbox/dts/test.dts | 13 + boot/Kconfig | 32 ++ boot/bootm.c | 74 +++ cmd/booti.c| 1 + cmd/bootm.c| 2 + cmd/bootz.c| 1 + configs/sandbox_defconfig | 1 + doc/usage/index.rst| 1 + doc/usage/measured_boot.rst| 23 + drivers/tpm/tpm2_tis_sandbox.c | 100 ++-- include/bootm.h| 11 + include/efi_tcg2.h | 44 -- include/image.h| 1 + include/test/suites.h | 1 + include/tpm-v2.h | 263 ++- lib/Kconfig| 4 + lib/efi_loader/Kconfig | 2 - lib/efi_loader/efi_tcg2.c | 823 - lib/tpm-v2.c | 814 test/boot/Makefile | 1 + test/boot/measurement.c| 66 +++ test/cmd_ut.c
[PATCH v12 3/8] tpm: Support boot measurements
Add TPM2 functions to support boot measurement. This includes starting up the TPM, initializing/appending the event log, and measuring the U-Boot version. Much of the code was used in the EFI subsystem, so remove it there and use the common functions. Signed-off-by: Eddie James --- Changes since v10: - Fix compile warning for armv7 (thanks Ilias) Changes since v8: - Fix log parsing again - any data corruption seen while replaying the event log was failing the entire measurement. - Added an option to ignore the existing log. This should only be used for systems that know that U-Boot is the first stage bootloader. This is necessary because the reserved memory region may persist through resets and so U-Boot attempts to append to the previous boot's log. Changes since v7: - Change name of tcg2_init_log and add more documentation - Add a check, when parsing the event log header, to ensure that the previous stage bootloader used all the active PCRs. - Change name of tcg2_log_find_end - Fix the greater than or equal to check to exit the log parsing - Make sure log_position is 0 if there is any error discovering the log - Return errors parsing the log if the data is corrupt so that we don't end up with half a log Changes since v6: - Added Linaro copyright for all the EFI moved code - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to copy any discovered event log to the user's log if passed in. Changes since v5: - Remove unused platform_get_eventlog in efi_tcg2.c - First look for tpm_event_log_* properties instead of linux,sml-* - Fix efi_tcg2.c compilation - Select SHA* configs Changes since v4: - Remove tcg2_measure_event function and check for NULL data in tcg2_measure_data - Use tpm_auto_startup - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function Changes since v3: - Reordered headers - Refactored more of EFI code into common code Removed digest_info structure and instead used the common alg_to_mask and alg_to_len Improved event log parsing in common code to get it equivalent to EFI Common code now extends PCR if previous bootloader stage couldn't No need to allocate memory in the common code, so EFI copies the discovered buffer like it did before Rename efi measure_event function Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions include/efi_tcg2.h| 44 -- include/tpm-v2.h | 259 lib/Kconfig | 4 + lib/efi_loader/efi_tcg2.c | 821 -- lib/tpm-v2.c | 814 + 5 files changed, 1154 insertions(+), 788 deletions(-) diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h index b1c3abd097..b21c5cb3dd 100644 --- a/include/efi_tcg2.h +++ b/include/efi_tcg2.h @@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability { #define BOOT_SERVICE_CAPABILITY_MIN \ offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks) -#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03" -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2 - -/** - * struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information - * - * @algorithm_id: algorithm defined in enum tpm2_algorithms - * @digest_size: size of the algorithm - */ -struct tcg_efi_spec_id_event_algorithm_size { - u16 algorithm_id; - u16 digest_size; -} __packed; - -/** - * struct TCG_EfiSpecIDEventStruct - content of the event log header - * - * @signature: signature, set to Spec ID Event03 - * @platform_class:class defined in TCG ACPI Specification - * Client Common Header. - * @spec_version_minor:minor version - * @spec_version_major:major version - * @spec_version_errata: major version - * @uintn_size:size of the efi_uintn_t fields used in various - * data structures used in this specification. - * 0x01 indicates u32 and 0x02 indicates u64 - * @number_of_algorithms: hashing algorithms used in this event log - * @digest_sizes: array of number_of_algorithms pairs - * 1st member defines the algorithm id - * 2nd member defines the algorithm size - */ -struct tcg_efi_spec_id_event { - u8 signature[16]; - u32 platform_class; - u8 spec_version_minor; - u8 spec_version_major; - u8 spec_errata; - u8 uintn_size; - u32 number_of_algorithms; - struct tcg_efi_spec_id_event_algorithm_size digest_sizes[]; -} __packed; - /** * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get
[PATCH v12 1/8] tpm: Fix spelling for tpmu_ha union
tmpu -> tpmu Signed-off-by: Eddie James Reviewed-by: Ilias Apalodimas --- include/tpm-v2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 2b6980e441..6684033deb 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -169,7 +169,7 @@ struct tcg_pcr_event { /** * Definition of TPMU_HA Union */ -union tmpu_ha { +union tpmu_ha { u8 sha1[TPM2_SHA1_DIGEST_SIZE]; u8 sha256[TPM2_SHA256_DIGEST_SIZE]; u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE]; @@ -185,7 +185,7 @@ union tmpu_ha { */ struct tpmt_ha { u16 hash_alg; - union tmpu_ha digest; + union tpmu_ha digest; } __packed; /** -- 2.39.3
[PATCH v12 6/8] doc: Add measured boot documentation
Briefly describe the feature and specify the requirements. Signed-off-by: Eddie James Reviewed-by: Simon Glass --- doc/usage/index.rst | 1 + doc/usage/measured_boot.rst | 23 +++ 2 files changed, 24 insertions(+) create mode 100644 doc/usage/measured_boot.rst diff --git a/doc/usage/index.rst b/doc/usage/index.rst index fa702920fa..fb043a8923 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -14,6 +14,7 @@ Use U-Boot partitions cmdline semihosting + measured_boot Shell commands -- diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst new file mode 100644 index 00..8357b1f480 --- /dev/null +++ b/doc/usage/measured_boot.rst @@ -0,0 +1,23 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Measured Boot += + +U-Boot can perform a measured boot, the process of hashing various components +of the boot process, extending the results in the TPM and logging the +component's measurement in memory for the operating system to consume. + +Requirements +- + +* A hardware TPM 2.0 supported by the U-Boot drivers +* CONFIG_TPM=y +* CONFIG_MEASURED_BOOT=y +* Device-tree configuration of the TPM device to specify the memory area + for event logging. The TPM device node must either contain a phandle to + a reserved memory region or "linux,sml-base" and "linux,sml-size" + indicating the address and size of the memory region. An example can be + found in arch/sandbox/dts/test.dts +* The operating system must also be configured to use the memory regions + specified in the U-Boot device-tree in order to make use of the event + log. -- 2.39.3
[PATCH v12 7/8] efi_loader: fix EFI_ENTRY point on get_active_pcr_banks
From: Ilias Apalodimas efi_tcg2_get_active_pcr_banks doesn't immediately call the EFI_ENTRY() wrapper once it enters the function. Move the call a few lines above to cover the error cases properly as well. Signed-off-by: Ilias Apalodimas --- lib/efi_loader/efi_tcg2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 7ada536568..dae1b166c8 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -949,16 +949,16 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this, struct udevice *dev; efi_status_t ret; + EFI_ENTRY("%p, %p", this, active_pcr_banks); + if (!this || !active_pcr_banks) { ret = EFI_INVALID_PARAMETER; goto out; } - ret = tcg2_platform_get_tpm2(); if (ret != EFI_SUCCESS) goto out; - EFI_ENTRY("%p, %p", this, active_pcr_banks); ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks); out: -- 2.39.3
[PATCH v12 8/8] test: use a non system PCR for testing PCR extend
From: Ilias Apalodimas We currently use PCR 0 for testing the PCR read/extend functionality in our selftests. How ever those PCRs are defined by the TCG spec for platform use. For example if the tests run *after* the efi subsystem initialization, which extends PCRs 0 & 7 it will give a false positive. So let's switch over to a PCR which is more suitable and is defined for OS use. It's worth noting that we are using PCR10 here, since PCR9 is used internally by U-Boot if we choose to measure the loaded DTB Reviewed-by: Simon Glass Signed-off-by: Ilias Apalodimas --- test/py/tests/test_tpm2.py | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py index c2579fa02c..47392b87a9 100644 --- a/test/py/tests/test_tpm2.py +++ b/test/py/tests/test_tpm2.py @@ -239,7 +239,7 @@ def test_tpm2_dam_parameters(u_boot_console): def test_tpm2_pcr_read(u_boot_console): """Execute a TPM2_PCR_Read command. -Perform a PCR read of the 0th PCR. Must be zero. +Perform a PCR read of the 10th PCR. Must be zero. """ if is_sandbox(u_boot_console): tpm2_sandbox_init(u_boot_console) @@ -247,7 +247,7 @@ def test_tpm2_pcr_read(u_boot_console): force_init(u_boot_console) ram = u_boot_utils.find_ram_base(u_boot_console) -read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % ram) +read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % ram) output = u_boot_console.run_command('echo $?') assert output.endswith('0') @@ -257,7 +257,7 @@ def test_tpm2_pcr_read(u_boot_console): updates = int(re.findall(r'\d+', str)[0]) # Check the output value -assert 'PCR #0 content' in read_pcr +assert 'PCR #10 content' in read_pcr assert '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' in read_pcr @pytest.mark.buildconfigspec('cmd_tpm_v2') @@ -275,19 +275,19 @@ def test_tpm2_pcr_extend(u_boot_console): force_init(u_boot_console) ram = u_boot_utils.find_ram_base(u_boot_console) -read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20)) +read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20)) output = u_boot_console.run_command('echo $?') assert output.endswith('0') str = re.findall(r'\d+ known updates', read_pcr)[0] updates = int(re.findall(r'\d+', str)[0]) -u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram) +u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram) output = u_boot_console.run_command('echo $?') assert output.endswith('0') # Read the value back into a different place so we can still use 'ram' as # our zero bytes -read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20)) +read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20)) output = u_boot_console.run_command('echo $?') assert output.endswith('0') assert 'f5 a5 fd 42 d1 6a 20 30 27 98 ef 6e d3 09 97 9b' in read_pcr @@ -297,11 +297,11 @@ def test_tpm2_pcr_extend(u_boot_console): new_updates = int(re.findall(r'\d+', str)[0]) assert (updates + 1) == new_updates -u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram) +u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram) output = u_boot_console.run_command('echo $?') assert output.endswith('0') -read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20)) +read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20)) output = u_boot_console.run_command('echo $?') assert output.endswith('0') assert '7a 05 01 f5 95 7b df 9c b3 a8 ff 49 66 f0 22 65' in read_pcr -- 2.39.3
[PATCH v12 2/8] tpm: sandbox: Update for needed TPM2 capabilities
The driver needs to support getting the PCRs in the capabilities command. Fix various other things and support the max number of PCRs for TPM2. Remove the !SANDBOX dependency for EFI TCG2 as well. Signed-off-by: Eddie James Reviewed-by: Simon Glass Acked-by: Ilias Apalodimas --- Changes since v8: - Use >= for checking the property against TPM2_PROPERTIES_OFFSET Changes since v5: - Remove the !SANDBOX dependency for EFI TCG2 drivers/tpm/tpm2_tis_sandbox.c | 100 - lib/efi_loader/Kconfig | 2 - 2 files changed, 72 insertions(+), 30 deletions(-) diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c index e4004cfcca..d15a28d9fc 100644 --- a/drivers/tpm/tpm2_tis_sandbox.c +++ b/drivers/tpm/tpm2_tis_sandbox.c @@ -22,11 +22,6 @@ enum tpm2_hierarchy { TPM2_HIERARCHY_NB, }; -/* Subset of supported capabilities */ -enum tpm2_capability { - TPM_CAP_TPM_PROPERTIES = 0x6, -}; - /* Subset of supported properties */ #define TPM2_PROPERTIES_OFFSET 0x020E @@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property { TPM2_PROPERTY_NB, }; -#define SANDBOX_TPM_PCR_NB 1 +#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS +#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8) /* * Information about our TPM emulation. This is preserved in the sandbox @@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, int i, j; /* TPM2_GetProperty */ - u32 capability, property, property_count; + u32 capability, property, property_count, val; /* TPM2_PCR_Read/Extend variables */ int pcr_index = 0; @@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, case TPM2_CC_GET_CAPABILITY: capability = get_unaligned_be32(sent); sent += sizeof(capability); - if (capability != TPM_CAP_TPM_PROPERTIES) { - printf("Sandbox TPM only support TPM_CAPABILITIES\n"); - return TPM2_RC_HANDLE; - } - property = get_unaligned_be32(sent); sent += sizeof(property); - property -= TPM2_PROPERTIES_OFFSET; - property_count = get_unaligned_be32(sent); sent += sizeof(property_count); - if (!property_count || - property + property_count > TPM2_PROPERTY_NB) { + + switch (capability) { + case TPM2_CAP_PCRS: + break; + case TPM2_CAP_TPM_PROPERTIES: + if (!property_count) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + + if (property >= TPM2_PROPERTIES_OFFSET && + ((property - TPM2_PROPERTIES_OFFSET) + +property_count > TPM2_PROPERTY_NB)) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + break; + default: + printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or " + "TPM2_CAP_TPM_PROPERTIES\n"); rc = TPM2_RC_HANDLE; return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); } @@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, put_unaligned_be32(capability, recv); recv += sizeof(capability); - /* Give the number of properties that follow */ - put_unaligned_be32(property_count, recv); - recv += sizeof(property_count); - - /* Fill with the properties */ - for (i = 0; i < property_count; i++) { - put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property + - i, recv); - recv += sizeof(property); - put_unaligned_be32(tpm->properties[property + i], - recv); - recv += sizeof(property); + switch (capability) { + case TPM2_CAP_PCRS: + /* Give the number of algorithms supported - just SHA256 */ + put_unaligned_be32(1, recv); + recv += sizeof(u32); + + /* Give SHA256 algorithm */ + put_unaligned_be16(TPM2_ALG_SHA256, recv); + recv += sizeof(u16); + + /* Se
[PATCH v12 4/8] bootm: Support boot measurement
Add a configuration option to measure the boot through the bootm function. Add the measurement state to the booti and bootz paths as well. Signed-off-by: Eddie James Reviewed-by: Simon Glass --- Changes since v8: - Added a configuration option to select to ignore any existing event log. This would only be selected for systems that know that U-Boot is the first stage bootloader. This is necessary because the reserved memory region may persist through resets and so U-Boot attempts to append to the previous boot's log. Changes since v6: - Added comment for bootm_measure - Fixed line length in bootm_measure boot/Kconfig| 32 + boot/bootm.c| 74 + cmd/booti.c | 1 + cmd/bootm.c | 2 ++ cmd/bootz.c | 1 + include/bootm.h | 11 include/image.h | 1 + 7 files changed, 122 insertions(+) diff --git a/boot/Kconfig b/boot/Kconfig index a01e6cb8aa..abbc72f4cf 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -685,6 +685,38 @@ config LEGACY_IMAGE_FORMAT loaded. If a board needs the legacy image format support in this case, enable it here. +config MEASURED_BOOT + bool "Measure boot images and configuration to TPM and event log" + depends on HASH && TPM_V2 + help + This option enables measurement of the boot process. Measurement + involves creating cryptographic hashes of the binary images that + are booting and storing them in the TPM. In addition, a log of + these hashes is stored in memory for the OS to verify the booted + images and configuration. Enable this if the OS has configured + some memory area for the event log and you intend to use some + attestation tools on your system. + +if MEASURED_BOOT + config MEASURE_DEVICETREE + bool "Measure the devicetree image" + default y if MEASURED_BOOT + help + On some platforms, the devicetree is not static as it may contain + random MAC addresses or other such data that changes each boot. + Therefore, it should not be measured into the TPM. In that case, + disable the measurement here. + + config MEASURE_IGNORE_LOG + bool "Ignore the existing event log" + default n + help + On platforms that use an event log memory region that persists + through system resets and are the first stage bootloader, then + this option should be enabled to ignore any existing data in the + event log memory region. +endif # MEASURED_BOOT + config SUPPORT_RAW_INITRD bool "Enable raw initrd images" help diff --git a/boot/bootm.c b/boot/bootm.c index b1c3afe0a3..11b6b3c292 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -22,6 +22,7 @@ #include #include #include +#include #if defined(CONFIG_CMD_USB) #include #endif @@ -673,6 +674,75 @@ int bootm_process_cmdline_env(int flags) return 0; } +int bootm_measure(struct bootm_headers *images) +{ + int ret = 0; + + /* Skip measurement if EFI is going to do it */ + if (images->os.os == IH_OS_EFI && + IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL) && + IS_ENABLED(CONFIG_BOOTM_EFI)) + return ret; + + if (IS_ENABLED(CONFIG_MEASURED_BOOT)) { + struct tcg2_event_log elog; + struct udevice *dev; + void *initrd_buf; + void *image_buf; + const char *s; + u32 rd_len; + bool ign; + + elog.log_size = 0; + ign = IS_ENABLED(CONFIG_MEASURE_IGNORE_LOG); + ret = tcg2_measurement_init(, , ign); + if (ret) + return ret; + + image_buf = map_sysmem(images->os.image_start, + images->os.image_len); + ret = tcg2_measure_data(dev, , 8, images->os.image_len, + image_buf, EV_COMPACT_HASH, + strlen("linux") + 1, (u8 *)"linux"); + if (ret) + goto unmap_image; + + rd_len = images->rd_end - images->rd_start; + initrd_buf = map_sysmem(images->rd_start, rd_len); + ret = tcg2_measure_data(dev, , 9, rd_len, initrd_buf, + EV_COMPACT_HASH, strlen("initrd") + 1, + (u8 *)"initrd"); + if (ret) + goto unmap_initrd; + + if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) { + ret = tcg2_measure_data(dev, , 0, images->ft_len, + (u8 *)images->ft_addr, +
Re: [PATCH v12 5/8] test: Add sandbox TPM boot measurement
On 10/13/23 12:22, Ilias Apalodimas wrote: Hi Eddie, This doesn't apply on -master, can you please rebase? Ugh I thought you wanted -next... I can rebase again. Thanks /Ilias On Thu, 12 Oct 2023 at 16:49, Eddie James wrote: Use the sandbox TPM driver to measure some boot images in a unit test case. Signed-off-by: Eddie James Reviewed-by: Simon Glass Acked-by: Ilias Apalodimas --- Changes since v5: - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT is enabled. arch/sandbox/dts/sandbox.dtsi | 13 +++ arch/sandbox/dts/test.dts | 13 +++ configs/sandbox_defconfig | 1 + include/test/suites.h | 1 + test/boot/Makefile| 1 + test/boot/measurement.c | 66 +++ test/cmd_ut.c | 4 +++ 7 files changed, 99 insertions(+) create mode 100644 test/boot/measurement.c diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index ff7e5584c5..241f397ba6 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -4,11 +4,23 @@ * and sandbox64 builds. */ +#include #include #define USB_CLASS_HUB 9 / { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman { }; @@ -342,6 +354,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; triangle { diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 9a863ea732..bb2ddd9bf2 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -9,6 +9,7 @@ /dts-v1/; +#include #include #include #include @@ -68,6 +69,17 @@ osd0 = "/osd"; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman: binman { }; @@ -1422,6 +1434,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; tpm { diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index d667cb9ae4..12c387a77e 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -349,3 +349,4 @@ CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y CONFIG_ARM_FFA_TRANSPORT=y +CONFIG_MEASURED_BOOT=y diff --git a/include/test/suites.h b/include/test/suites.h index 1c7dc65966..48ed549c13 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -45,6 +45,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); +int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/test/boot/Makefile b/test/boot/Makefile index 52947580ae..068522cb9e 100644 --- a/test/boot/Makefile +++ b/test/boot/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o obj-$(CONFIG_FIT) += image.o +obj-$(CONFIG_MEASURED_BOOT) += measurement.o obj-$(CONFIG_EXPO) += expo.o obj-$(CONFIG_CEDIT) += cedit.o diff --git a/test/boot/measurement.c b/test/boot/measurement.c new file mode 100644 index 00..9db2ed324c --- /dev/null +++ b/test/boot/measurement.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for measured boot functions + * + * Copyright 2023 IBM Corp. + * Written by Eddie James + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MEASUREMENT_TEST(_name, _flags)\ + UNIT_TEST(_name, _flags, measurement_test) + +static int measure(struct unit_test_state *uts) +{ + struct bootm_headers images; + const size_t size = 1024; + u8 *kernel; + u8 *initrd; + size_t i; + + kernel = malloc(size); + initrd = malloc(size); + + images.os.image_start = map_to_sysmem(kernel); + images.os.image_len = size; + + images.rd_start = map_to_sysmem(initrd); + images.rd_end = images.r
[PATCH v13 3/8] tpm: Support boot measurements
Add TPM2 functions to support boot measurement. This includes starting up the TPM, initializing/appending the event log, and measuring the U-Boot version. Much of the code was used in the EFI subsystem, so remove it there and use the common functions. Signed-off-by: Eddie James --- Changes since v10: - Fix compile warning for armv7 (thanks Ilias) Changes since v8: - Fix log parsing again - any data corruption seen while replaying the event log was failing the entire measurement. - Added an option to ignore the existing log. This should only be used for systems that know that U-Boot is the first stage bootloader. This is necessary because the reserved memory region may persist through resets and so U-Boot attempts to append to the previous boot's log. Changes since v7: - Change name of tcg2_init_log and add more documentation - Add a check, when parsing the event log header, to ensure that the previous stage bootloader used all the active PCRs. - Change name of tcg2_log_find_end - Fix the greater than or equal to check to exit the log parsing - Make sure log_position is 0 if there is any error discovering the log - Return errors parsing the log if the data is corrupt so that we don't end up with half a log Changes since v6: - Added Linaro copyright for all the EFI moved code - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to copy any discovered event log to the user's log if passed in. Changes since v5: - Remove unused platform_get_eventlog in efi_tcg2.c - First look for tpm_event_log_* properties instead of linux,sml-* - Fix efi_tcg2.c compilation - Select SHA* configs Changes since v4: - Remove tcg2_measure_event function and check for NULL data in tcg2_measure_data - Use tpm_auto_startup - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function Changes since v3: - Reordered headers - Refactored more of EFI code into common code Removed digest_info structure and instead used the common alg_to_mask and alg_to_len Improved event log parsing in common code to get it equivalent to EFI Common code now extends PCR if previous bootloader stage couldn't No need to allocate memory in the common code, so EFI copies the discovered buffer like it did before Rename efi measure_event function Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions include/efi_tcg2.h| 44 -- include/tpm-v2.h | 259 lib/Kconfig | 4 + lib/efi_loader/efi_tcg2.c | 821 -- lib/tpm-v2.c | 814 + 5 files changed, 1154 insertions(+), 788 deletions(-) diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h index b1c3abd097..b21c5cb3dd 100644 --- a/include/efi_tcg2.h +++ b/include/efi_tcg2.h @@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability { #define BOOT_SERVICE_CAPABILITY_MIN \ offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks) -#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03" -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2 - -/** - * struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information - * - * @algorithm_id: algorithm defined in enum tpm2_algorithms - * @digest_size: size of the algorithm - */ -struct tcg_efi_spec_id_event_algorithm_size { - u16 algorithm_id; - u16 digest_size; -} __packed; - -/** - * struct TCG_EfiSpecIDEventStruct - content of the event log header - * - * @signature: signature, set to Spec ID Event03 - * @platform_class:class defined in TCG ACPI Specification - * Client Common Header. - * @spec_version_minor:minor version - * @spec_version_major:major version - * @spec_version_errata: major version - * @uintn_size:size of the efi_uintn_t fields used in various - * data structures used in this specification. - * 0x01 indicates u32 and 0x02 indicates u64 - * @number_of_algorithms: hashing algorithms used in this event log - * @digest_sizes: array of number_of_algorithms pairs - * 1st member defines the algorithm id - * 2nd member defines the algorithm size - */ -struct tcg_efi_spec_id_event { - u8 signature[16]; - u32 platform_class; - u8 spec_version_minor; - u8 spec_version_major; - u8 spec_errata; - u8 uintn_size; - u32 number_of_algorithms; - struct tcg_efi_spec_id_event_algorithm_size digest_sizes[]; -} __packed; - /** * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get
[PATCH v13 8/8] test: use a non system PCR for testing PCR extend
From: Ilias Apalodimas We currently use PCR 0 for testing the PCR read/extend functionality in our selftests. How ever those PCRs are defined by the TCG spec for platform use. For example if the tests run *after* the efi subsystem initialization, which extends PCRs 0 & 7 it will give a false positive. So let's switch over to a PCR which is more suitable and is defined for OS use. It's worth noting that we are using PCR10 here, since PCR9 is used internally by U-Boot if we choose to measure the loaded DTB Reviewed-by: Simon Glass Signed-off-by: Ilias Apalodimas --- test/py/tests/test_tpm2.py | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py index c2579fa02c..47392b87a9 100644 --- a/test/py/tests/test_tpm2.py +++ b/test/py/tests/test_tpm2.py @@ -239,7 +239,7 @@ def test_tpm2_dam_parameters(u_boot_console): def test_tpm2_pcr_read(u_boot_console): """Execute a TPM2_PCR_Read command. -Perform a PCR read of the 0th PCR. Must be zero. +Perform a PCR read of the 10th PCR. Must be zero. """ if is_sandbox(u_boot_console): tpm2_sandbox_init(u_boot_console) @@ -247,7 +247,7 @@ def test_tpm2_pcr_read(u_boot_console): force_init(u_boot_console) ram = u_boot_utils.find_ram_base(u_boot_console) -read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % ram) +read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % ram) output = u_boot_console.run_command('echo $?') assert output.endswith('0') @@ -257,7 +257,7 @@ def test_tpm2_pcr_read(u_boot_console): updates = int(re.findall(r'\d+', str)[0]) # Check the output value -assert 'PCR #0 content' in read_pcr +assert 'PCR #10 content' in read_pcr assert '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' in read_pcr @pytest.mark.buildconfigspec('cmd_tpm_v2') @@ -275,19 +275,19 @@ def test_tpm2_pcr_extend(u_boot_console): force_init(u_boot_console) ram = u_boot_utils.find_ram_base(u_boot_console) -read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20)) +read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20)) output = u_boot_console.run_command('echo $?') assert output.endswith('0') str = re.findall(r'\d+ known updates', read_pcr)[0] updates = int(re.findall(r'\d+', str)[0]) -u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram) +u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram) output = u_boot_console.run_command('echo $?') assert output.endswith('0') # Read the value back into a different place so we can still use 'ram' as # our zero bytes -read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20)) +read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20)) output = u_boot_console.run_command('echo $?') assert output.endswith('0') assert 'f5 a5 fd 42 d1 6a 20 30 27 98 ef 6e d3 09 97 9b' in read_pcr @@ -297,11 +297,11 @@ def test_tpm2_pcr_extend(u_boot_console): new_updates = int(re.findall(r'\d+', str)[0]) assert (updates + 1) == new_updates -u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram) +u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram) output = u_boot_console.run_command('echo $?') assert output.endswith('0') -read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20)) +read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20)) output = u_boot_console.run_command('echo $?') assert output.endswith('0') assert '7a 05 01 f5 95 7b df 9c b3 a8 ff 49 66 f0 22 65' in read_pcr -- 2.39.3
[PATCH v13 4/8] bootm: Support boot measurement
Add a configuration option to measure the boot through the bootm function. Add the measurement state to the booti and bootz paths as well. Signed-off-by: Eddie James Reviewed-by: Simon Glass --- Changes since v8: - Added a configuration option to select to ignore any existing event log. This would only be selected for systems that know that U-Boot is the first stage bootloader. This is necessary because the reserved memory region may persist through resets and so U-Boot attempts to append to the previous boot's log. Changes since v6: - Added comment for bootm_measure - Fixed line length in bootm_measure boot/Kconfig| 32 + boot/bootm.c| 74 + cmd/booti.c | 1 + cmd/bootm.c | 2 ++ cmd/bootz.c | 1 + include/bootm.h | 11 include/image.h | 1 + 7 files changed, 122 insertions(+) diff --git a/boot/Kconfig b/boot/Kconfig index a01e6cb8aa..abbc72f4cf 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -685,6 +685,38 @@ config LEGACY_IMAGE_FORMAT loaded. If a board needs the legacy image format support in this case, enable it here. +config MEASURED_BOOT + bool "Measure boot images and configuration to TPM and event log" + depends on HASH && TPM_V2 + help + This option enables measurement of the boot process. Measurement + involves creating cryptographic hashes of the binary images that + are booting and storing them in the TPM. In addition, a log of + these hashes is stored in memory for the OS to verify the booted + images and configuration. Enable this if the OS has configured + some memory area for the event log and you intend to use some + attestation tools on your system. + +if MEASURED_BOOT + config MEASURE_DEVICETREE + bool "Measure the devicetree image" + default y if MEASURED_BOOT + help + On some platforms, the devicetree is not static as it may contain + random MAC addresses or other such data that changes each boot. + Therefore, it should not be measured into the TPM. In that case, + disable the measurement here. + + config MEASURE_IGNORE_LOG + bool "Ignore the existing event log" + default n + help + On platforms that use an event log memory region that persists + through system resets and are the first stage bootloader, then + this option should be enabled to ignore any existing data in the + event log memory region. +endif # MEASURED_BOOT + config SUPPORT_RAW_INITRD bool "Enable raw initrd images" help diff --git a/boot/bootm.c b/boot/bootm.c index 8f96a80d42..cb61485c22 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -23,6 +23,7 @@ #include #include #include +#include #if defined(CONFIG_CMD_USB) #include #endif @@ -673,6 +674,75 @@ int bootm_process_cmdline_env(int flags) return 0; } +int bootm_measure(struct bootm_headers *images) +{ + int ret = 0; + + /* Skip measurement if EFI is going to do it */ + if (images->os.os == IH_OS_EFI && + IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL) && + IS_ENABLED(CONFIG_BOOTM_EFI)) + return ret; + + if (IS_ENABLED(CONFIG_MEASURED_BOOT)) { + struct tcg2_event_log elog; + struct udevice *dev; + void *initrd_buf; + void *image_buf; + const char *s; + u32 rd_len; + bool ign; + + elog.log_size = 0; + ign = IS_ENABLED(CONFIG_MEASURE_IGNORE_LOG); + ret = tcg2_measurement_init(, , ign); + if (ret) + return ret; + + image_buf = map_sysmem(images->os.image_start, + images->os.image_len); + ret = tcg2_measure_data(dev, , 8, images->os.image_len, + image_buf, EV_COMPACT_HASH, + strlen("linux") + 1, (u8 *)"linux"); + if (ret) + goto unmap_image; + + rd_len = images->rd_end - images->rd_start; + initrd_buf = map_sysmem(images->rd_start, rd_len); + ret = tcg2_measure_data(dev, , 9, rd_len, initrd_buf, + EV_COMPACT_HASH, strlen("initrd") + 1, + (u8 *)"initrd"); + if (ret) + goto unmap_initrd; + + if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) { + ret = tcg2_measure_data(dev, , 0, images->ft_len, + (u8 *)images->ft_addr, +
[PATCH v13 6/8] doc: Add measured boot documentation
Briefly describe the feature and specify the requirements. Signed-off-by: Eddie James Reviewed-by: Simon Glass --- Changes since v12: - Add a bit of detail about OS usage and what pieces are measured doc/usage/index.rst | 1 + doc/usage/measured_boot.rst | 31 +++ 2 files changed, 32 insertions(+) create mode 100644 doc/usage/measured_boot.rst diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 98b4719c40..bf53bb6bda 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -14,6 +14,7 @@ Use U-Boot partitions cmdline semihosting + measured_boot Shell commands -- diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst new file mode 100644 index 00..0aad590859 --- /dev/null +++ b/doc/usage/measured_boot.rst @@ -0,0 +1,31 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Measured Boot += + +U-Boot can perform a measured boot, the process of hashing various components +of the boot process, extending the results in the TPM and logging the +component's measurement in memory for the operating system to consume. + +By default, U-Boot will measure the operating system (linux) image, the +initrd image, and the "bootargs" environment variable. By enabling +CONFIG_MEASURE_DEVICETREE, U-Boot will also measure the devicetree image. + +The operating system typically would verify that the hashes found in the +TPM PCRs match the contents of the event log. This can further be checked +against the hash results of previous boots. + +Requirements +- + +* A hardware TPM 2.0 supported by the U-Boot drivers +* CONFIG_TPM=y +* CONFIG_MEASURED_BOOT=y +* Device-tree configuration of the TPM device to specify the memory area + for event logging. The TPM device node must either contain a phandle to + a reserved memory region or "linux,sml-base" and "linux,sml-size" + indicating the address and size of the memory region. An example can be + found in arch/sandbox/dts/test.dts +* The operating system must also be configured to use the memory regions + specified in the U-Boot device-tree in order to make use of the event + log. -- 2.39.3
Re: [PATCH v12 6/8] doc: Add measured boot documentation
On 10/12/23 10:29, Simon Glass wrote: Hi Eddie, On Thu, 12 Oct 2023 at 08:08, Eddie James wrote: Briefly describe the feature and specify the requirements. Signed-off-by: Eddie James Reviewed-by: Simon Glass This could use a bit more detail. What pieces are measured? What DT binding is used for the TPM? How is the info checked by the OS or whatever? Sure, I'll add a little bit more. The DT binding is described in the requirements section. --- doc/usage/index.rst | 1 + doc/usage/measured_boot.rst | 23 +++ 2 files changed, 24 insertions(+) create mode 100644 doc/usage/measured_boot.rst diff --git a/doc/usage/index.rst b/doc/usage/index.rst index fa702920fa..fb043a8923 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -14,6 +14,7 @@ Use U-Boot partitions cmdline semihosting + measured_boot Shell commands -- diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst new file mode 100644 index 00..8357b1f480 --- /dev/null +++ b/doc/usage/measured_boot.rst @@ -0,0 +1,23 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Measured Boot += + +U-Boot can perform a measured boot, the process of hashing various components +of the boot process, extending the results in the TPM and logging the +component's measurement in memory for the operating system to consume. + +Requirements +- + +* A hardware TPM 2.0 supported by the U-Boot drivers +* CONFIG_TPM=y +* CONFIG_MEASURED_BOOT=y +* Device-tree configuration of the TPM device to specify the memory area + for event logging. The TPM device node must either contain a phandle to + a reserved memory region or "linux,sml-base" and "linux,sml-size" + indicating the address and size of the memory region. An example can be + found in arch/sandbox/dts/test.dts +* The operating system must also be configured to use the memory regions + specified in the U-Boot device-tree in order to make use of the event + log. Regards, Simon
[PATCH v13 5/8] test: Add sandbox TPM boot measurement
Use the sandbox TPM driver to measure some boot images in a unit test case. Signed-off-by: Eddie James Reviewed-by: Simon Glass Acked-by: Ilias Apalodimas --- Changes since v5: - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT is enabled. arch/sandbox/dts/sandbox.dtsi | 13 +++ arch/sandbox/dts/test.dts | 13 +++ configs/sandbox_defconfig | 1 + include/test/suites.h | 1 + test/boot/Makefile| 1 + test/boot/measurement.c | 66 +++ test/cmd_ut.c | 4 +++ 7 files changed, 99 insertions(+) create mode 100644 test/boot/measurement.c diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index ff7e5584c5..241f397ba6 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -4,11 +4,23 @@ * and sandbox64 builds. */ +#include #include #define USB_CLASS_HUB 9 / { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman { }; @@ -342,6 +354,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; triangle { diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index e430347356..67159b3d01 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -9,6 +9,7 @@ /dts-v1/; +#include #include #include #include @@ -68,6 +69,17 @@ osd0 = "/osd"; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman: binman { }; @@ -1423,6 +1435,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; tpm { diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 47417cb039..757dcac4ca 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -349,3 +349,4 @@ CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +CONFIG_MEASURED_BOOT=y diff --git a/include/test/suites.h b/include/test/suites.h index 1c7dc65966..48ed549c13 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -45,6 +45,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); +int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/test/boot/Makefile b/test/boot/Makefile index 52947580ae..068522cb9e 100644 --- a/test/boot/Makefile +++ b/test/boot/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o obj-$(CONFIG_FIT) += image.o +obj-$(CONFIG_MEASURED_BOOT) += measurement.o obj-$(CONFIG_EXPO) += expo.o obj-$(CONFIG_CEDIT) += cedit.o diff --git a/test/boot/measurement.c b/test/boot/measurement.c new file mode 100644 index 00..9db2ed324c --- /dev/null +++ b/test/boot/measurement.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for measured boot functions + * + * Copyright 2023 IBM Corp. + * Written by Eddie James + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MEASUREMENT_TEST(_name, _flags)\ + UNIT_TEST(_name, _flags, measurement_test) + +static int measure(struct unit_test_state *uts) +{ + struct bootm_headers images; + const size_t size = 1024; + u8 *kernel; + u8 *initrd; + size_t i; + + kernel = malloc(size); + initrd = malloc(size); + + images.os.image_start = map_to_sysmem(kernel); + images.os.image_len = size; + + images.rd_start = map_to_sysmem(initrd); + images.rd_end = images.rd_start + size; + + images.ft_addr = malloc(size); + images.ft_len = size; + + env_set("bootargs", "measurement testing"); + + for (i = 0; i < size; ++i) { + kernel[i] = 0xf0 | (i & 0xf); + in
[PATCH v13 1/8] tpm: Fix spelling for tpmu_ha union
tmpu -> tpmu Signed-off-by: Eddie James Reviewed-by: Ilias Apalodimas --- include/tpm-v2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 2b6980e441..6684033deb 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -169,7 +169,7 @@ struct tcg_pcr_event { /** * Definition of TPMU_HA Union */ -union tmpu_ha { +union tpmu_ha { u8 sha1[TPM2_SHA1_DIGEST_SIZE]; u8 sha256[TPM2_SHA256_DIGEST_SIZE]; u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE]; @@ -185,7 +185,7 @@ union tmpu_ha { */ struct tpmt_ha { u16 hash_alg; - union tmpu_ha digest; + union tpmu_ha digest; } __packed; /** -- 2.39.3
[PATCH v13 0/8] tpm: Support boot measurements
This series adds support for measuring the boot images more generically than the existing EFI support. Several EFI functions have been moved to the TPM layer. The series includes optional measurement from the bootm command. A new test case has been added for the bootm measurement to test the new path, and the sandbox TPM2 driver has been updated to support this use case. Changes since v12: - Rebase on master. - Add detail to documentation. Changes since v11: - Rebase on next. Sorry for the delay (been on leave). Changes since v10: - Fix commit message on efi_loader change - Drop python test change - Squash armv7 fix from Ilias Changes since v9: - Rebase and add Ilias' fixes (thanks!) Changes since v8: - Fix a sandbox driver off-by-one error in checking the property type. - Fix log parsing again - any data corruption seen while replaying the event log was failing the entire measurement. - Added an option to ignore the existing log and a configuration option for systems to select that for the bootm measurement. This would only be selected for systems that know that U-Boot is the first stage bootloader. This is necessary because the reserved memory region may persist through resets and so U-Boot attempts to append to the previous boot's log. Changes since v7: - Change name of tcg2_init_log and add more documentation - Add a check, when parsing the event log header, to ensure that the previous stage bootloader used all the active PCRs. - Change name of tcg2_log_find_end - Fix the greater than or equal to check to exit the log parsing - Make sure log_position is 0 if there is any error discovering the log - Return errors parsing the log if the data is corrupt so that we don't end up with half a log Changes since v6: - Added comment for bootm_measure - Fixed line length in bootm_measure - Added Linaro copyright for all the EFI moved code - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to copy any discovered event log to the user's log if passed in. Changes since v5: - Re-ordered the patches to put the sandbox TPM driver patch second - Remove unused platform_get_eventlog in efi_tcg2.c - First look for tpm_event_log_* properties instead of linux,sml-* - Fix efi_tcg2.c compilation - Select SHA* configs - Remove the !SANDBOX dependency for EFI TCG2 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT is enabled Changes since v4: - Remove tcg2_measure_event function and check for NULL data in tcg2_measure_data - Use tpm_auto_startup - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function - Change PCR indexes for initrd and dtb - Drop u8 casting in measurement test - Use bullets in documentation Changes since v3: - Reordered headers - Refactored more of EFI code into common code Removed digest_info structure and instead used the common alg_to_mask and alg_to_len Improved event log parsing in common code to get it equivalent to EFI Common code now extends PCR if previous bootloader stage couldn't No need to allocate memory in the common code, so EFI copies the discovered buffer like it did before Rename efi measure_event function Changes since v2: - Add documentation. - Changed reserved memory address to the top of the RAM for sandbox dts. - Add measure state to booti and bootz. - Skip measurement for EFI images that should be measured Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions. - Add test case - Drop #ifdefs for bootm - Add devicetree measurement config option - Update sandbox TPM driver Eddie James (6): tpm: Fix spelling for tpmu_ha union tpm: sandbox: Update for needed TPM2 capabilities tpm: Support boot measurements bootm: Support boot measurement test: Add sandbox TPM boot measurement doc: Add measured boot documentation Ilias Apalodimas (2): efi_loader: fix EFI_ENTRY point on get_active_pcr_banks test: use a non system PCR for testing PCR extend arch/sandbox/dts/sandbox.dtsi | 13 + arch/sandbox/dts/test.dts | 13 + boot/Kconfig | 32 ++ boot/bootm.c | 74 +++ cmd/booti.c| 1 + cmd/bootm.c| 2 + cmd/bootz.c| 1 + configs/sandbox_defconfig | 1 + doc/usage/index.rst| 1 + doc/usage/measured_boot.rst| 23 + drivers/tpm/tpm2_tis_sandbox.c | 100 ++-- include/bootm.h| 11 + include/efi_tcg2.h | 44 -- include/image.h| 1 + include/test/suites.h | 1 + include/tpm-v2.h | 263 ++- lib/Kconfig| 4 + lib/efi_loader/Kconfig | 2 - lib/efi_loader/efi_tcg2.c | 823 - lib/tpm-v2.c | 814 test/boot/Makefile | 1
[PATCH v13 2/8] tpm: sandbox: Update for needed TPM2 capabilities
The driver needs to support getting the PCRs in the capabilities command. Fix various other things and support the max number of PCRs for TPM2. Remove the !SANDBOX dependency for EFI TCG2 as well. Signed-off-by: Eddie James Reviewed-by: Simon Glass Acked-by: Ilias Apalodimas --- Changes since v8: - Use >= for checking the property against TPM2_PROPERTIES_OFFSET Changes since v5: - Remove the !SANDBOX dependency for EFI TCG2 drivers/tpm/tpm2_tis_sandbox.c | 100 - lib/efi_loader/Kconfig | 2 - 2 files changed, 72 insertions(+), 30 deletions(-) diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c index e4004cfcca..d15a28d9fc 100644 --- a/drivers/tpm/tpm2_tis_sandbox.c +++ b/drivers/tpm/tpm2_tis_sandbox.c @@ -22,11 +22,6 @@ enum tpm2_hierarchy { TPM2_HIERARCHY_NB, }; -/* Subset of supported capabilities */ -enum tpm2_capability { - TPM_CAP_TPM_PROPERTIES = 0x6, -}; - /* Subset of supported properties */ #define TPM2_PROPERTIES_OFFSET 0x020E @@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property { TPM2_PROPERTY_NB, }; -#define SANDBOX_TPM_PCR_NB 1 +#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS +#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8) /* * Information about our TPM emulation. This is preserved in the sandbox @@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, int i, j; /* TPM2_GetProperty */ - u32 capability, property, property_count; + u32 capability, property, property_count, val; /* TPM2_PCR_Read/Extend variables */ int pcr_index = 0; @@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, case TPM2_CC_GET_CAPABILITY: capability = get_unaligned_be32(sent); sent += sizeof(capability); - if (capability != TPM_CAP_TPM_PROPERTIES) { - printf("Sandbox TPM only support TPM_CAPABILITIES\n"); - return TPM2_RC_HANDLE; - } - property = get_unaligned_be32(sent); sent += sizeof(property); - property -= TPM2_PROPERTIES_OFFSET; - property_count = get_unaligned_be32(sent); sent += sizeof(property_count); - if (!property_count || - property + property_count > TPM2_PROPERTY_NB) { + + switch (capability) { + case TPM2_CAP_PCRS: + break; + case TPM2_CAP_TPM_PROPERTIES: + if (!property_count) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + + if (property >= TPM2_PROPERTIES_OFFSET && + ((property - TPM2_PROPERTIES_OFFSET) + +property_count > TPM2_PROPERTY_NB)) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + break; + default: + printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or " + "TPM2_CAP_TPM_PROPERTIES\n"); rc = TPM2_RC_HANDLE; return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); } @@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, put_unaligned_be32(capability, recv); recv += sizeof(capability); - /* Give the number of properties that follow */ - put_unaligned_be32(property_count, recv); - recv += sizeof(property_count); - - /* Fill with the properties */ - for (i = 0; i < property_count; i++) { - put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property + - i, recv); - recv += sizeof(property); - put_unaligned_be32(tpm->properties[property + i], - recv); - recv += sizeof(property); + switch (capability) { + case TPM2_CAP_PCRS: + /* Give the number of algorithms supported - just SHA256 */ + put_unaligned_be32(1, recv); + recv += sizeof(u32); + + /* Give SHA256 algorithm */ + put_unaligned_be16(TPM2_ALG_SHA256, recv); + recv += sizeof(u16); + + /* Se
[PATCH v13 7/8] efi_loader: fix EFI_ENTRY point on get_active_pcr_banks
From: Ilias Apalodimas efi_tcg2_get_active_pcr_banks doesn't immediately call the EFI_ENTRY() wrapper once it enters the function. Move the call a few lines above to cover the error cases properly as well. Signed-off-by: Ilias Apalodimas --- lib/efi_loader/efi_tcg2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 7ada536568..dae1b166c8 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -949,16 +949,16 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this, struct udevice *dev; efi_status_t ret; + EFI_ENTRY("%p, %p", this, active_pcr_banks); + if (!this || !active_pcr_banks) { ret = EFI_INVALID_PARAMETER; goto out; } - ret = tcg2_platform_get_tpm2(); if (ret != EFI_SUCCESS) goto out; - EFI_ENTRY("%p, %p", this, active_pcr_banks); ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks); out: -- 2.39.3
Re: [PATCH v13 0/8] tpm: Support boot measurements
On 10/19/23 17:49, Ilias Apalodimas wrote: Hi Eddie, Does the series compile for you against -master? For qemu_arm64_defonfig I am getting compilation errors both locally and on the CI https://source.denx.de/u-boot/custodians/u-boot-tpm/-/jobs/717362#L39 Yea it was a problem rebasing. I'll send v14 soon. Thanks, Eddie Thanks /Ilias On Thu, 19 Oct 2023 at 19:45, Ilias Apalodimas wrote: Thanks Eddie I've queued this up on public CI. I also have an internal one, this one failed to add the TF-A eventlog, but everything else looks fine. I'll have a look tomorrow, but since this used to work on earlier versions I suspect it's going to be trivial to fix Cheers /Ilias On Thu, 19 Oct 2023 at 19:21, Eddie James wrote: This series adds support for measuring the boot images more generically than the existing EFI support. Several EFI functions have been moved to the TPM layer. The series includes optional measurement from the bootm command. A new test case has been added for the bootm measurement to test the new path, and the sandbox TPM2 driver has been updated to support this use case. Changes since v12: - Rebase on master. - Add detail to documentation. Changes since v11: - Rebase on next. Sorry for the delay (been on leave). Changes since v10: - Fix commit message on efi_loader change - Drop python test change - Squash armv7 fix from Ilias Changes since v9: - Rebase and add Ilias' fixes (thanks!) Changes since v8: - Fix a sandbox driver off-by-one error in checking the property type. - Fix log parsing again - any data corruption seen while replaying the event log was failing the entire measurement. - Added an option to ignore the existing log and a configuration option for systems to select that for the bootm measurement. This would only be selected for systems that know that U-Boot is the first stage bootloader. This is necessary because the reserved memory region may persist through resets and so U-Boot attempts to append to the previous boot's log. Changes since v7: - Change name of tcg2_init_log and add more documentation - Add a check, when parsing the event log header, to ensure that the previous stage bootloader used all the active PCRs. - Change name of tcg2_log_find_end - Fix the greater than or equal to check to exit the log parsing - Make sure log_position is 0 if there is any error discovering the log - Return errors parsing the log if the data is corrupt so that we don't end up with half a log Changes since v6: - Added comment for bootm_measure - Fixed line length in bootm_measure - Added Linaro copyright for all the EFI moved code - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to copy any discovered event log to the user's log if passed in. Changes since v5: - Re-ordered the patches to put the sandbox TPM driver patch second - Remove unused platform_get_eventlog in efi_tcg2.c - First look for tpm_event_log_* properties instead of linux,sml-* - Fix efi_tcg2.c compilation - Select SHA* configs - Remove the !SANDBOX dependency for EFI TCG2 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT is enabled Changes since v4: - Remove tcg2_measure_event function and check for NULL data in tcg2_measure_data - Use tpm_auto_startup - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function - Change PCR indexes for initrd and dtb - Drop u8 casting in measurement test - Use bullets in documentation Changes since v3: - Reordered headers - Refactored more of EFI code into common code Removed digest_info structure and instead used the common alg_to_mask and alg_to_len Improved event log parsing in common code to get it equivalent to EFI Common code now extends PCR if previous bootloader stage couldn't No need to allocate memory in the common code, so EFI copies the discovered buffer like it did before Rename efi measure_event function Changes since v2: - Add documentation. - Changed reserved memory address to the top of the RAM for sandbox dts. - Add measure state to booti and bootz. - Skip measurement for EFI images that should be measured Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions. - Add test case - Drop #ifdefs for bootm - Add devicetree measurement config option - Update sandbox TPM driver Eddie James (6): tpm: Fix spelling for tpmu_ha union tpm: sandbox: Update for needed TPM2 capabilities tpm: Support boot measurements bootm: Support boot measurement test: Add sandbox TPM boot measurement doc: Add measured boot documentation Ilias Apalodimas (2): efi_loader: fix EFI_ENTRY point on get_active_pcr_banks test: use a non system PCR for testing PCR extend arch/sandbox/dts/sandbox.dtsi | 13 + arch/sandbox/dts/test.dts | 13 + boot/Kconfig
[PATCH v14 0/8] tpm: Support boot measurements
This series adds support for measuring the boot images more generically than the existing EFI support. Several EFI functions have been moved to the TPM layer. The series includes optional measurement from the bootm command. A new test case has been added for the bootm measurement to test the new path, and the sandbox TPM2 driver has been updated to support this use case. Changes since v13: - Rebase without messing up efi_tcg2.c (duplicate functions) Changes since v12: - Rebase on master. - Add detail to documentation. Changes since v11: - Rebase on next. Sorry for the delay (been on leave). Changes since v10: - Fix commit message on efi_loader change - Drop python test change - Squash armv7 fix from Ilias Changes since v9: - Rebase and add Ilias' fixes (thanks!) Changes since v8: - Fix a sandbox driver off-by-one error in checking the property type. - Fix log parsing again - any data corruption seen while replaying the event log was failing the entire measurement. - Added an option to ignore the existing log and a configuration option for systems to select that for the bootm measurement. This would only be selected for systems that know that U-Boot is the first stage bootloader. This is necessary because the reserved memory region may persist through resets and so U-Boot attempts to append to the previous boot's log. Changes since v7: - Change name of tcg2_init_log and add more documentation - Add a check, when parsing the event log header, to ensure that the previous stage bootloader used all the active PCRs. - Change name of tcg2_log_find_end - Fix the greater than or equal to check to exit the log parsing - Make sure log_position is 0 if there is any error discovering the log - Return errors parsing the log if the data is corrupt so that we don't end up with half a log Changes since v6: - Added comment for bootm_measure - Fixed line length in bootm_measure - Added Linaro copyright for all the EFI moved code - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to copy any discovered event log to the user's log if passed in. Changes since v5: - Re-ordered the patches to put the sandbox TPM driver patch second - Remove unused platform_get_eventlog in efi_tcg2.c - First look for tpm_event_log_* properties instead of linux,sml-* - Fix efi_tcg2.c compilation - Select SHA* configs - Remove the !SANDBOX dependency for EFI TCG2 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT is enabled Changes since v4: - Remove tcg2_measure_event function and check for NULL data in tcg2_measure_data - Use tpm_auto_startup - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function - Change PCR indexes for initrd and dtb - Drop u8 casting in measurement test - Use bullets in documentation Changes since v3: - Reordered headers - Refactored more of EFI code into common code Removed digest_info structure and instead used the common alg_to_mask and alg_to_len Improved event log parsing in common code to get it equivalent to EFI Common code now extends PCR if previous bootloader stage couldn't No need to allocate memory in the common code, so EFI copies the discovered buffer like it did before Rename efi measure_event function Changes since v2: - Add documentation. - Changed reserved memory address to the top of the RAM for sandbox dts. - Add measure state to booti and bootz. - Skip measurement for EFI images that should be measured Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions. - Add test case - Drop #ifdefs for bootm - Add devicetree measurement config option - Update sandbox TPM driver Eddie James (6): tpm: Fix spelling for tpmu_ha union tpm: sandbox: Update for needed TPM2 capabilities tpm: Support boot measurements bootm: Support boot measurement test: Add sandbox TPM boot measurement doc: Add measured boot documentation Ilias Apalodimas (2): efi_loader: fix EFI_ENTRY point on get_active_pcr_banks test: use a non system PCR for testing PCR extend arch/sandbox/dts/sandbox.dtsi | 13 + arch/sandbox/dts/test.dts | 13 + boot/Kconfig | 32 + boot/bootm.c | 74 +++ cmd/booti.c|1 + cmd/bootm.c|2 + cmd/bootz.c|1 + configs/sandbox_defconfig |1 + doc/usage/index.rst|1 + doc/usage/measured_boot.rst| 31 + drivers/tpm/tpm2_tis_sandbox.c | 100 ++- include/bootm.h| 11 + include/efi_tcg2.h | 44 -- include/image.h|1 + include/test/suites.h |1 + include/tpm-v2.h | 263 +++- lib/Kconfig|4 + lib/efi_loader/Kconfig |2 - lib/efi_loader/efi_tcg2.c | 1055 +++- lib/tpm-v2.c
[PATCH v14 5/8] test: Add sandbox TPM boot measurement
Use the sandbox TPM driver to measure some boot images in a unit test case. Signed-off-by: Eddie James Reviewed-by: Simon Glass Acked-by: Ilias Apalodimas --- Changes since v5: - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT is enabled. arch/sandbox/dts/sandbox.dtsi | 13 +++ arch/sandbox/dts/test.dts | 13 +++ configs/sandbox_defconfig | 1 + include/test/suites.h | 1 + test/boot/Makefile| 1 + test/boot/measurement.c | 66 +++ test/cmd_ut.c | 4 +++ 7 files changed, 99 insertions(+) create mode 100644 test/boot/measurement.c diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index ff7e5584c5..241f397ba6 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -4,11 +4,23 @@ * and sandbox64 builds. */ +#include #include #define USB_CLASS_HUB 9 / { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman { }; @@ -342,6 +354,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; triangle { diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index e430347356..67159b3d01 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -9,6 +9,7 @@ /dts-v1/; +#include #include #include #include @@ -68,6 +69,17 @@ osd0 = "/osd"; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman: binman { }; @@ -1423,6 +1435,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; tpm { diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 47417cb039..757dcac4ca 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -349,3 +349,4 @@ CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +CONFIG_MEASURED_BOOT=y diff --git a/include/test/suites.h b/include/test/suites.h index 1c7dc65966..48ed549c13 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -45,6 +45,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); +int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/test/boot/Makefile b/test/boot/Makefile index 52947580ae..068522cb9e 100644 --- a/test/boot/Makefile +++ b/test/boot/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o obj-$(CONFIG_FIT) += image.o +obj-$(CONFIG_MEASURED_BOOT) += measurement.o obj-$(CONFIG_EXPO) += expo.o obj-$(CONFIG_CEDIT) += cedit.o diff --git a/test/boot/measurement.c b/test/boot/measurement.c new file mode 100644 index 00..9db2ed324c --- /dev/null +++ b/test/boot/measurement.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for measured boot functions + * + * Copyright 2023 IBM Corp. + * Written by Eddie James + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MEASUREMENT_TEST(_name, _flags)\ + UNIT_TEST(_name, _flags, measurement_test) + +static int measure(struct unit_test_state *uts) +{ + struct bootm_headers images; + const size_t size = 1024; + u8 *kernel; + u8 *initrd; + size_t i; + + kernel = malloc(size); + initrd = malloc(size); + + images.os.image_start = map_to_sysmem(kernel); + images.os.image_len = size; + + images.rd_start = map_to_sysmem(initrd); + images.rd_end = images.rd_start + size; + + images.ft_addr = malloc(size); + images.ft_len = size; + + env_set("bootargs", "measurement testing"); + + for (i = 0; i < size; ++i) { + kernel[i] = 0xf0 | (i & 0xf); + in
[PATCH v14 6/8] doc: Add measured boot documentation
Briefly describe the feature and specify the requirements. Signed-off-by: Eddie James Reviewed-by: Simon Glass --- Changes since v12: - Add a bit of detail about OS usage and what pieces are measured doc/usage/index.rst | 1 + doc/usage/measured_boot.rst | 31 +++ 2 files changed, 32 insertions(+) create mode 100644 doc/usage/measured_boot.rst diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 98b4719c40..bf53bb6bda 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -14,6 +14,7 @@ Use U-Boot partitions cmdline semihosting + measured_boot Shell commands -- diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst new file mode 100644 index 00..0aad590859 --- /dev/null +++ b/doc/usage/measured_boot.rst @@ -0,0 +1,31 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Measured Boot += + +U-Boot can perform a measured boot, the process of hashing various components +of the boot process, extending the results in the TPM and logging the +component's measurement in memory for the operating system to consume. + +By default, U-Boot will measure the operating system (linux) image, the +initrd image, and the "bootargs" environment variable. By enabling +CONFIG_MEASURE_DEVICETREE, U-Boot will also measure the devicetree image. + +The operating system typically would verify that the hashes found in the +TPM PCRs match the contents of the event log. This can further be checked +against the hash results of previous boots. + +Requirements +- + +* A hardware TPM 2.0 supported by the U-Boot drivers +* CONFIG_TPM=y +* CONFIG_MEASURED_BOOT=y +* Device-tree configuration of the TPM device to specify the memory area + for event logging. The TPM device node must either contain a phandle to + a reserved memory region or "linux,sml-base" and "linux,sml-size" + indicating the address and size of the memory region. An example can be + found in arch/sandbox/dts/test.dts +* The operating system must also be configured to use the memory regions + specified in the U-Boot device-tree in order to make use of the event + log. -- 2.39.3
[PATCH v14 2/8] tpm: sandbox: Update for needed TPM2 capabilities
The driver needs to support getting the PCRs in the capabilities command. Fix various other things and support the max number of PCRs for TPM2. Remove the !SANDBOX dependency for EFI TCG2 as well. Signed-off-by: Eddie James Reviewed-by: Simon Glass Acked-by: Ilias Apalodimas --- Changes since v8: - Use >= for checking the property against TPM2_PROPERTIES_OFFSET Changes since v5: - Remove the !SANDBOX dependency for EFI TCG2 drivers/tpm/tpm2_tis_sandbox.c | 100 - lib/efi_loader/Kconfig | 2 - 2 files changed, 72 insertions(+), 30 deletions(-) diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c index e4004cfcca..d15a28d9fc 100644 --- a/drivers/tpm/tpm2_tis_sandbox.c +++ b/drivers/tpm/tpm2_tis_sandbox.c @@ -22,11 +22,6 @@ enum tpm2_hierarchy { TPM2_HIERARCHY_NB, }; -/* Subset of supported capabilities */ -enum tpm2_capability { - TPM_CAP_TPM_PROPERTIES = 0x6, -}; - /* Subset of supported properties */ #define TPM2_PROPERTIES_OFFSET 0x020E @@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property { TPM2_PROPERTY_NB, }; -#define SANDBOX_TPM_PCR_NB 1 +#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS +#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8) /* * Information about our TPM emulation. This is preserved in the sandbox @@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, int i, j; /* TPM2_GetProperty */ - u32 capability, property, property_count; + u32 capability, property, property_count, val; /* TPM2_PCR_Read/Extend variables */ int pcr_index = 0; @@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, case TPM2_CC_GET_CAPABILITY: capability = get_unaligned_be32(sent); sent += sizeof(capability); - if (capability != TPM_CAP_TPM_PROPERTIES) { - printf("Sandbox TPM only support TPM_CAPABILITIES\n"); - return TPM2_RC_HANDLE; - } - property = get_unaligned_be32(sent); sent += sizeof(property); - property -= TPM2_PROPERTIES_OFFSET; - property_count = get_unaligned_be32(sent); sent += sizeof(property_count); - if (!property_count || - property + property_count > TPM2_PROPERTY_NB) { + + switch (capability) { + case TPM2_CAP_PCRS: + break; + case TPM2_CAP_TPM_PROPERTIES: + if (!property_count) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + + if (property >= TPM2_PROPERTIES_OFFSET && + ((property - TPM2_PROPERTIES_OFFSET) + +property_count > TPM2_PROPERTY_NB)) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + break; + default: + printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or " + "TPM2_CAP_TPM_PROPERTIES\n"); rc = TPM2_RC_HANDLE; return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); } @@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, put_unaligned_be32(capability, recv); recv += sizeof(capability); - /* Give the number of properties that follow */ - put_unaligned_be32(property_count, recv); - recv += sizeof(property_count); - - /* Fill with the properties */ - for (i = 0; i < property_count; i++) { - put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property + - i, recv); - recv += sizeof(property); - put_unaligned_be32(tpm->properties[property + i], - recv); - recv += sizeof(property); + switch (capability) { + case TPM2_CAP_PCRS: + /* Give the number of algorithms supported - just SHA256 */ + put_unaligned_be32(1, recv); + recv += sizeof(u32); + + /* Give SHA256 algorithm */ + put_unaligned_be16(TPM2_ALG_SHA256, recv); + recv += sizeof(u16); + + /* Se
[PATCH v14 1/8] tpm: Fix spelling for tpmu_ha union
tmpu -> tpmu Signed-off-by: Eddie James Reviewed-by: Ilias Apalodimas --- include/tpm-v2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 2b6980e441..6684033deb 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -169,7 +169,7 @@ struct tcg_pcr_event { /** * Definition of TPMU_HA Union */ -union tmpu_ha { +union tpmu_ha { u8 sha1[TPM2_SHA1_DIGEST_SIZE]; u8 sha256[TPM2_SHA256_DIGEST_SIZE]; u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE]; @@ -185,7 +185,7 @@ union tmpu_ha { */ struct tpmt_ha { u16 hash_alg; - union tmpu_ha digest; + union tpmu_ha digest; } __packed; /** -- 2.39.3
[PATCH v14 3/8] tpm: Support boot measurements
Add TPM2 functions to support boot measurement. This includes starting up the TPM, initializing/appending the event log, and measuring the U-Boot version. Much of the code was used in the EFI subsystem, so remove it there and use the common functions. Signed-off-by: Eddie James --- Changes since v13: - Fix rebase since v11 and prevent duplicate efi_tcg2.c functions Changes since v10: - Fix compile warning for armv7 (thanks Ilias) Changes since v8: - Fix log parsing again - any data corruption seen while replaying the event log was failing the entire measurement. - Added an option to ignore the existing log. This should only be used for systems that know that U-Boot is the first stage bootloader. This is necessary because the reserved memory region may persist through resets and so U-Boot attempts to append to the previous boot's log. Changes since v7: - Change name of tcg2_init_log and add more documentation - Add a check, when parsing the event log header, to ensure that the previous stage bootloader used all the active PCRs. - Change name of tcg2_log_find_end - Fix the greater than or equal to check to exit the log parsing - Make sure log_position is 0 if there is any error discovering the log - Return errors parsing the log if the data is corrupt so that we don't end up with half a log Changes since v6: - Added Linaro copyright for all the EFI moved code - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to copy any discovered event log to the user's log if passed in. Changes since v5: - Remove unused platform_get_eventlog in efi_tcg2.c - First look for tpm_event_log_* properties instead of linux,sml-* - Fix efi_tcg2.c compilation - Select SHA* configs Changes since v4: - Remove tcg2_measure_event function and check for NULL data in tcg2_measure_data - Use tpm_auto_startup - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function Changes since v3: - Reordered headers - Refactored more of EFI code into common code Removed digest_info structure and instead used the common alg_to_mask and alg_to_len Improved event log parsing in common code to get it equivalent to EFI Common code now extends PCR if previous bootloader stage couldn't No need to allocate memory in the common code, so EFI copies the discovered buffer like it did before Rename efi measure_event function Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions include/efi_tcg2.h| 44 -- include/tpm-v2.h | 259 + lib/Kconfig |4 + lib/efi_loader/efi_tcg2.c | 1053 +++-- lib/tpm-v2.c | 814 5 files changed, 1154 insertions(+), 1020 deletions(-) diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h index b1c3abd097..b21c5cb3dd 100644 --- a/include/efi_tcg2.h +++ b/include/efi_tcg2.h @@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability { #define BOOT_SERVICE_CAPABILITY_MIN \ offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks) -#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03" -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2 - -/** - * struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information - * - * @algorithm_id: algorithm defined in enum tpm2_algorithms - * @digest_size: size of the algorithm - */ -struct tcg_efi_spec_id_event_algorithm_size { - u16 algorithm_id; - u16 digest_size; -} __packed; - -/** - * struct TCG_EfiSpecIDEventStruct - content of the event log header - * - * @signature: signature, set to Spec ID Event03 - * @platform_class:class defined in TCG ACPI Specification - * Client Common Header. - * @spec_version_minor:minor version - * @spec_version_major:major version - * @spec_version_errata: major version - * @uintn_size:size of the efi_uintn_t fields used in various - * data structures used in this specification. - * 0x01 indicates u32 and 0x02 indicates u64 - * @number_of_algorithms: hashing algorithms used in this event log - * @digest_sizes: array of number_of_algorithms pairs - * 1st member defines the algorithm id - * 2nd member defines the algorithm size - */ -struct tcg_efi_spec_id_event { - u8 signature[16]; - u32 platform_class; - u8 spec_version_minor; - u8 spec_version_major; - u8 spec_errata; - u8 uintn_size; - u32 number_of_algorithms; - struct tcg_efi_spec_id_event_algorithm_size digest_sizes[]; -
[PATCH v14 4/8] bootm: Support boot measurement
Add a configuration option to measure the boot through the bootm function. Add the measurement state to the booti and bootz paths as well. Signed-off-by: Eddie James Reviewed-by: Simon Glass --- Changes since v8: - Added a configuration option to select to ignore any existing event log. This would only be selected for systems that know that U-Boot is the first stage bootloader. This is necessary because the reserved memory region may persist through resets and so U-Boot attempts to append to the previous boot's log. Changes since v6: - Added comment for bootm_measure - Fixed line length in bootm_measure boot/Kconfig| 32 + boot/bootm.c| 74 + cmd/booti.c | 1 + cmd/bootm.c | 2 ++ cmd/bootz.c | 1 + include/bootm.h | 11 include/image.h | 1 + 7 files changed, 122 insertions(+) diff --git a/boot/Kconfig b/boot/Kconfig index a01e6cb8aa..abbc72f4cf 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -685,6 +685,38 @@ config LEGACY_IMAGE_FORMAT loaded. If a board needs the legacy image format support in this case, enable it here. +config MEASURED_BOOT + bool "Measure boot images and configuration to TPM and event log" + depends on HASH && TPM_V2 + help + This option enables measurement of the boot process. Measurement + involves creating cryptographic hashes of the binary images that + are booting and storing them in the TPM. In addition, a log of + these hashes is stored in memory for the OS to verify the booted + images and configuration. Enable this if the OS has configured + some memory area for the event log and you intend to use some + attestation tools on your system. + +if MEASURED_BOOT + config MEASURE_DEVICETREE + bool "Measure the devicetree image" + default y if MEASURED_BOOT + help + On some platforms, the devicetree is not static as it may contain + random MAC addresses or other such data that changes each boot. + Therefore, it should not be measured into the TPM. In that case, + disable the measurement here. + + config MEASURE_IGNORE_LOG + bool "Ignore the existing event log" + default n + help + On platforms that use an event log memory region that persists + through system resets and are the first stage bootloader, then + this option should be enabled to ignore any existing data in the + event log memory region. +endif # MEASURED_BOOT + config SUPPORT_RAW_INITRD bool "Enable raw initrd images" help diff --git a/boot/bootm.c b/boot/bootm.c index 8f96a80d42..cb61485c22 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -23,6 +23,7 @@ #include #include #include +#include #if defined(CONFIG_CMD_USB) #include #endif @@ -673,6 +674,75 @@ int bootm_process_cmdline_env(int flags) return 0; } +int bootm_measure(struct bootm_headers *images) +{ + int ret = 0; + + /* Skip measurement if EFI is going to do it */ + if (images->os.os == IH_OS_EFI && + IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL) && + IS_ENABLED(CONFIG_BOOTM_EFI)) + return ret; + + if (IS_ENABLED(CONFIG_MEASURED_BOOT)) { + struct tcg2_event_log elog; + struct udevice *dev; + void *initrd_buf; + void *image_buf; + const char *s; + u32 rd_len; + bool ign; + + elog.log_size = 0; + ign = IS_ENABLED(CONFIG_MEASURE_IGNORE_LOG); + ret = tcg2_measurement_init(, , ign); + if (ret) + return ret; + + image_buf = map_sysmem(images->os.image_start, + images->os.image_len); + ret = tcg2_measure_data(dev, , 8, images->os.image_len, + image_buf, EV_COMPACT_HASH, + strlen("linux") + 1, (u8 *)"linux"); + if (ret) + goto unmap_image; + + rd_len = images->rd_end - images->rd_start; + initrd_buf = map_sysmem(images->rd_start, rd_len); + ret = tcg2_measure_data(dev, , 9, rd_len, initrd_buf, + EV_COMPACT_HASH, strlen("initrd") + 1, + (u8 *)"initrd"); + if (ret) + goto unmap_initrd; + + if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) { + ret = tcg2_measure_data(dev, , 0, images->ft_len, + (u8 *)images->ft_addr, +
[PATCH v14 8/8] test: use a non system PCR for testing PCR extend
From: Ilias Apalodimas We currently use PCR 0 for testing the PCR read/extend functionality in our selftests. How ever those PCRs are defined by the TCG spec for platform use. For example if the tests run *after* the efi subsystem initialization, which extends PCRs 0 & 7 it will give a false positive. So let's switch over to a PCR which is more suitable and is defined for OS use. It's worth noting that we are using PCR10 here, since PCR9 is used internally by U-Boot if we choose to measure the loaded DTB Reviewed-by: Simon Glass Signed-off-by: Ilias Apalodimas --- test/py/tests/test_tpm2.py | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py index c2579fa02c..47392b87a9 100644 --- a/test/py/tests/test_tpm2.py +++ b/test/py/tests/test_tpm2.py @@ -239,7 +239,7 @@ def test_tpm2_dam_parameters(u_boot_console): def test_tpm2_pcr_read(u_boot_console): """Execute a TPM2_PCR_Read command. -Perform a PCR read of the 0th PCR. Must be zero. +Perform a PCR read of the 10th PCR. Must be zero. """ if is_sandbox(u_boot_console): tpm2_sandbox_init(u_boot_console) @@ -247,7 +247,7 @@ def test_tpm2_pcr_read(u_boot_console): force_init(u_boot_console) ram = u_boot_utils.find_ram_base(u_boot_console) -read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % ram) +read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % ram) output = u_boot_console.run_command('echo $?') assert output.endswith('0') @@ -257,7 +257,7 @@ def test_tpm2_pcr_read(u_boot_console): updates = int(re.findall(r'\d+', str)[0]) # Check the output value -assert 'PCR #0 content' in read_pcr +assert 'PCR #10 content' in read_pcr assert '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' in read_pcr @pytest.mark.buildconfigspec('cmd_tpm_v2') @@ -275,19 +275,19 @@ def test_tpm2_pcr_extend(u_boot_console): force_init(u_boot_console) ram = u_boot_utils.find_ram_base(u_boot_console) -read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20)) +read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20)) output = u_boot_console.run_command('echo $?') assert output.endswith('0') str = re.findall(r'\d+ known updates', read_pcr)[0] updates = int(re.findall(r'\d+', str)[0]) -u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram) +u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram) output = u_boot_console.run_command('echo $?') assert output.endswith('0') # Read the value back into a different place so we can still use 'ram' as # our zero bytes -read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20)) +read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20)) output = u_boot_console.run_command('echo $?') assert output.endswith('0') assert 'f5 a5 fd 42 d1 6a 20 30 27 98 ef 6e d3 09 97 9b' in read_pcr @@ -297,11 +297,11 @@ def test_tpm2_pcr_extend(u_boot_console): new_updates = int(re.findall(r'\d+', str)[0]) assert (updates + 1) == new_updates -u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram) +u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram) output = u_boot_console.run_command('echo $?') assert output.endswith('0') -read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20)) +read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20)) output = u_boot_console.run_command('echo $?') assert output.endswith('0') assert '7a 05 01 f5 95 7b df 9c b3 a8 ff 49 66 f0 22 65' in read_pcr -- 2.39.3
[PATCH v14 7/8] efi_loader: fix EFI_ENTRY point on get_active_pcr_banks
From: Ilias Apalodimas efi_tcg2_get_active_pcr_banks doesn't immediately call the EFI_ENTRY() wrapper once it enters the function. Move the call a few lines above to cover the error cases properly as well. Signed-off-by: Ilias Apalodimas --- lib/efi_loader/efi_tcg2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index b87c7900a8..2eaa12b83b 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -717,16 +717,16 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this, struct udevice *dev; efi_status_t ret; + EFI_ENTRY("%p, %p", this, active_pcr_banks); + if (!this || !active_pcr_banks) { ret = EFI_INVALID_PARAMETER; goto out; } - ret = tcg2_platform_get_tpm2(); if (ret != EFI_SUCCESS) goto out; - EFI_ENTRY("%p, %p", this, active_pcr_banks); ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks); out: -- 2.39.3
Re: [PATCH 2/2] tpm: add support for TPMv2.x I2C chips
On 5/23/22 01:12, Ilias Apalodimas wrote: Hi Eddie, Thanks for the patch. [...] +static const struct tpm_tis_chip_data tpm_tis_std_chip_data = { + .pcr_count = 24, + .pcr_select_min = 3, +}; + +static const struct udevice_id tpm_tis_i2c_ids[] = { + { + .compatible = "nuvoton,npct75x", + .data = (ulong)_tis_std_chip_data, + }, + { + .compatible = "tcg,tpm-tis-i2c", + .data = (ulong)_tis_std_chip_data, + }, + { } +}; + +U_BOOT_DRIVER(tpm_tis_i2c) = { + .name = "tpm_tis_i2c", + .id = UCLASS_TPM, + .of_match = tpm_tis_i2c_ids, + .ops = _tis_i2c_ops, + .probe = tpm_tis_i2c_probe, + .remove = tpm_tis_i2c_remove, + .priv_auto_alloc_size = sizeof(struct tpm_chip), Shouldn't this be .priv_auto only? IIRC we got rid of the .priv_auto_alloc_size a while back? If so I can fix this while merging Yes, I think so. I tested with an older u-boot (openbmc uses a modified v2019.04) with all the TPM core patches, and I think I missed this bit in rebasing. Thanks, Eddie Regards /Ilias +}; -- 2.27.0
[PATCH] arm: dts: ast2600: Add I2C pinctrl
Set the pinctrl groups for each I2C bus. These are essential to I2C operating correctly. Signed-off-by: Eddie James --- arch/arm/dts/ast2600.dtsi | 33 + 1 file changed, 33 insertions(+) diff --git a/arch/arm/dts/ast2600.dtsi b/arch/arm/dts/ast2600.dtsi index 64074309b7..ef5b131ac0 100644 --- a/arch/arm/dts/ast2600.dtsi +++ b/arch/arm/dts/ast2600.dtsi @@ -833,6 +833,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c1_default>; status = "disabled"; }; @@ -846,6 +848,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c2_default>; status = "disabled"; }; @@ -859,6 +863,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c3_default>; }; i2c3: i2c@200 { @@ -871,6 +877,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c4_default>; }; i2c4: i2c@280 { @@ -883,6 +891,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c5_default>; }; i2c5: i2c@300 { @@ -895,6 +905,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c6_default>; }; i2c6: i2c@380 { @@ -907,6 +919,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c7_default>; }; i2c7: i2c@400 { @@ -919,6 +933,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c8_default>; }; i2c8: i2c@480 { @@ -931,6 +947,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c9_default>; }; i2c9: i2c@500 { @@ -943,6 +961,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c10_default>; status = "disabled"; }; @@ -956,6 +976,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c11_default>; status = "disabled"; }; @@ -969,6 +991,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c12_default>; status = "disabled"; }; @@ -982,6 +1006,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c13_default>; status = "disabled"; }; @@ -995,6 +1021,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c14_default>; status = "disabled"; }; @@ -1008,6 +1036,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c15_default>; status = "disabled"; }; @@ -1021,6 +1051,8 @@ bus-frequency = <10>; interrupts = ; clocks = < ASPEED_CLK_APB2>; + pinctrl-names = "default"; + pinctrl-0 = <_i2c16_default>; status = "disabled"; }; @@ -1246,6 +1278,7 @@ function = "I2C1"; groups = "I2C1"; }; + pinctrl_i2c2_default: i2c2_default { function = "I2C2"; groups = "I2C2"; -- 2.31.1
[PATCH 2/2] tpm: add support for TPMv2.x I2C chips
Add the tpm2_tis_i2c driver that should support any TPMv2 compliant I2C chips, such as the NPCT75X chip. Signed-off-by: Eddie James --- drivers/tpm/Kconfig| 9 ++ drivers/tpm/Makefile | 1 + drivers/tpm/tpm2_tis_i2c.c | 171 + 3 files changed, 181 insertions(+) create mode 100644 drivers/tpm/tpm2_tis_i2c.c diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig index eceff27d5f..d59102d9a6 100644 --- a/drivers/tpm/Kconfig +++ b/drivers/tpm/Kconfig @@ -185,6 +185,15 @@ config TPM2_TIS_SPI to the device using the standard TPM Interface Specification (TIS) protocol. +config TPM2_TIS_I2C + bool "Enable support for TPMv2.x I2C chips" + depends on TPM_V2 && DM_I2C + help + This driver supports TPMv2.x devices connected on the I2C bus. + The usual TPM operations and the 'tpm' command can be used to talk + to the device using the standard TPM Interface Specification (TIS) + protocol. + config TPM2_FTPM_TEE bool "TEE based fTPM Interface" depends on TEE && OPTEE && TPM_V2 diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile index 51725230c7..9540fd7fe7 100644 --- a/drivers/tpm/Makefile +++ b/drivers/tpm/Makefile @@ -13,5 +13,6 @@ obj-$(CONFIG_TPM_ST33ZP24_SPI) += tpm_tis_st33zp24_spi.o obj-$(CONFIG_$(SPL_TPL_)TPM2_CR50_I2C) += cr50_i2c.o obj-$(CONFIG_TPM2_TIS_SANDBOX) += tpm2_tis_sandbox.o sandbox_common.o obj-$(CONFIG_TPM2_TIS_SPI) += tpm2_tis_core.o tpm2_tis_spi.o +obj-$(CONFIG_TPM2_TIS_I2C) += tpm2_tis_core.o tpm2_tis_i2c.o obj-$(CONFIG_TPM2_FTPM_TEE) += tpm2_ftpm_tee.o obj-$(CONFIG_TPM2_MMIO) += tpm2_tis_core.o tpm2_tis_mmio.o diff --git a/drivers/tpm/tpm2_tis_i2c.c b/drivers/tpm/tpm2_tis_i2c.c new file mode 100644 index 00..33cd5bb84b --- /dev/null +++ b/drivers/tpm/tpm2_tis_i2c.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2022 IBM Corp. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tpm_tis.h" +#include "tpm_internal.h" + +struct tpm_tis_chip_data { + unsigned int pcr_count; + unsigned int pcr_select_min; +}; + +static uint tpm_tis_i2c_address_to_register(u32 addr) +{ + addr &= 0xFFF; + + /* +* Adapt register addresses that have changed compared to older TIS +* version. +*/ + switch (addr) { + case TPM_ACCESS(0): + return 0x04; + case TPM_DID_VID(0): + return 0x48; + case TPM_RID(0): + return 0x4C; + default: + return addr; + } +} + +static int tpm_tis_i2c_read(struct udevice *dev, u32 addr, u16 len, u8 *in) +{ + int rc; + int count = 0; + uint reg = tpm_tis_i2c_address_to_register(addr); + + do { + rc = dm_i2c_read(dev, reg, in, len); + udelay(SLEEP_DURATION_US); + } while (rc && count++ < MAX_COUNT); + + return rc; +} + +static int tpm_tis_i2c_write(struct udevice *dev, u32 addr, u16 len, +const u8 *out) +{ + int rc; + int count = 0; + uint reg = tpm_tis_i2c_address_to_register(addr); + + do { + rc = dm_i2c_write(dev, reg, out, len); + udelay(SLEEP_DURATION_US); + } while (rc && count++ < MAX_COUNT); + + return rc; +} + +static int tpm_tis_i2c_read32(struct udevice *dev, u32 addr, u32 *result) +{ + __le32 result_le; + int rc; + + rc = tpm_tis_i2c_read(dev, addr, sizeof(u32), (u8 *)_le); + if (!rc) + *result = le32_to_cpu(result_le); + + return rc; +} + +static int tpm_tis_i2c_write32(struct udevice *dev, u32 addr, u32 value) +{ + __le32 value_le = cpu_to_le32(value); + + return tpm_tis_i2c_write(dev, addr, sizeof(value), (u8 *)_le); +} + +static struct tpm_tis_phy_ops phy_ops = { + .read_bytes = tpm_tis_i2c_read, + .write_bytes = tpm_tis_i2c_write, + .read32 = tpm_tis_i2c_read32, + .write32 = tpm_tis_i2c_write32, +}; + +static int tpm_tis_i2c_probe(struct udevice *udev) +{ + struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(udev); + struct tpm_chip_priv *priv = dev_get_uclass_priv(udev); + int rc; + u8 loc = 0; + + tpm_tis_ops_register(udev, _ops); + + /* +* Force locality 0. The core driver doesn't actually write the +* locality register and instead just reads/writes various access +* bits of the selected locality. +*/ + rc = dm_i2c_write(udev, 0, , 1); + if (rc) + return rc; + + rc = tpm_tis_init(udev); + if (rc) + return rc; + + priv->pcr_count = drv_data->pcr_count; + priv->pcr_select_m
[PATCH 1/2] tpm: core: Set timeouts before requesting locality
Requesting the locality uses the timeout values, so they need to be set beforehand. Signed-off-by: Eddie James --- drivers/tpm/tpm2_tis_core.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/tpm/tpm2_tis_core.c b/drivers/tpm/tpm2_tis_core.c index 51392c4584..985a816219 100644 --- a/drivers/tpm/tpm2_tis_core.c +++ b/drivers/tpm/tpm2_tis_core.c @@ -433,15 +433,16 @@ int tpm_tis_init(struct udevice *dev) log_err("Driver bug. No bus ops defined\n"); return -1; } - ret = tpm_tis_request_locality(dev, 0); - if (ret) - return ret; chip->timeout_a = TIS_SHORT_TIMEOUT_MS; chip->timeout_b = TIS_LONG_TIMEOUT_MS; chip->timeout_c = TIS_SHORT_TIMEOUT_MS; chip->timeout_d = TIS_SHORT_TIMEOUT_MS; + ret = tpm_tis_request_locality(dev, 0); + if (ret) + return ret; + /* Disable interrupts */ phy_ops->read32(dev, TPM_INT_ENABLE(chip->locality), ); tmp |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT | -- 2.27.0
[PATCH 0/2] tpm: Add support for TPMv2.x I2C chips
Add a tpm driver that should support any TPMv2 compliant I2C chips, such as the NPCT75X chip. In my testing I also noticed that the timeouts weren't set before requesting the locality so I have included a fix. Eddie James (2): tpm: core: Set timeouts before requesting locality tpm: add support for TPMv2.x I2C chips drivers/tpm/Kconfig | 9 ++ drivers/tpm/Makefile| 1 + drivers/tpm/tpm2_tis_core.c | 7 +- drivers/tpm/tpm2_tis_i2c.c | 171 4 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 drivers/tpm/tpm2_tis_i2c.c -- 2.27.0
[PATCH] i2c: ast_i2c: Remove SCL direct drive mode
SCL direct drive mode prevents communication with devices that do clock stretching, so disable. The Linux driver doesn't use this mode, and the engine can handle clock stretching. Signed-off-by: Eddie James --- drivers/i2c/ast_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c index 2d3fecaa14..8b24a260c0 100644 --- a/drivers/i2c/ast_i2c.c +++ b/drivers/i2c/ast_i2c.c @@ -76,7 +76,7 @@ static void ast_i2c_init_bus(struct udevice *dev) /* Enable Master Mode. Assuming single-master */ writel(I2CD_MASTER_EN | I2CD_M_SDA_LOCK_EN - | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN, + | I2CD_MULTI_MASTER_DIS, >regs->fcr); /* Enable Interrupts */ writel(I2CD_INTR_TX_ACK -- 2.27.0
Re: [PATCH v2 5/5] test: Add sandbox TPM boot measurement
On 1/9/23 17:26, Heinrich Schuchardt wrote: On 1/10/23 00:13, Heinrich Schuchardt wrote: On 1/9/23 22:55, Eddie James wrote: Use the sandbox TPM driver to measure some boot images in a unit test case. $ ./u-boot -T -c "ut measurement" Running 1 measurement tests Test: measure: measurement.c Failures: 0 Signed-off-by: Eddie James --- arch/sandbox/dts/test.dts | 12 +++ configs/sandbox_defconfig | 1 + include/test/suites.h | 1 + test/boot/Makefile | 1 + test/boot/measurement.c | 66 +++ test/cmd_ut.c | 2 ++ 6 files changed, 83 insertions(+) create mode 100644 test/boot/measurement.c diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index dffe10adbf..ad90bf0541 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -66,6 +66,17 @@ osd0 = "/osd"; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log@d0e000 { + no-map; + reg = <0x00d0e000 0x2000>; How should this work if you don't define linux,sml-base and linux,sml-size? I have sent a patch to the linux list for using a reserved memory region, as I have also added in the u-boot TPM layer for the event log. https://patchwork.kernel.org/project/linux-integrity/patch/20230103162010.381214-1-eaja...@linux.ibm.com/ Thanks, Eddie Best regards Heinrich This would limit the file loaded at $loadaddr = 0x0 to 13 MiB. Please, choose a much higher address. Or change $loadaddr, e.g. use loadaddr = kernel_addr_r = 0x100. I would prefer raising loadaddr. Best regards Heinrich + }; + }; + binman: binman { }; @@ -1332,6 +1343,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; uart0: serial { diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index de799b5cea..5ac115f2d8 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -335,3 +335,4 @@ CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +CONFIG_MEASURED_BOOT=y diff --git a/include/test/suites.h b/include/test/suites.h index a01000e127..f9284871b0 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -43,6 +43,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); +int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/test/boot/Makefile b/test/boot/Makefile index d724629d3b..24cc20bdff 100644 --- a/test/boot/Makefile +++ b/test/boot/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o obj-$(CONFIG_FIT) += image.o +obj-$(CONFIG_MEASURED_BOOT) += measurement.o ifdef CONFIG_OF_LIVE obj-$(CONFIG_BOOTMETH_VBE_SIMPLE) += vbe_simple.o diff --git a/test/boot/measurement.c b/test/boot/measurement.c new file mode 100644 index 00..2155208894 --- /dev/null +++ b/test/boot/measurement.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for measured boot functions + * + * Copyright 2023 IBM Corp. + * Written by Eddie James + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MEASUREMENT_TEST(_name, _flags) \ + UNIT_TEST(_name, _flags, measurement_test) + +static int measure(struct unit_test_state *uts) +{ + struct bootm_headers images; + const size_t size = 1024; + u8 *kernel; + u8 *initrd; + size_t i; + + kernel = malloc(size); + initrd = malloc(size); + + images.os.image_start = map_to_sysmem(kernel); + images.os.image_len = size; + + images.rd_start = map_to_sysmem(initrd); + images.rd_end = images.rd_start + size; + + images.ft_addr = malloc(size); + images.ft_len = size; + + env_set("bootargs", "measurement testing"); + + for (i = 0; i < size; ++i) { + kernel[i] = (u8)(0xf0 | (i & 0xf)); + initrd[i] = (u8)((i & 0xf0) | 0xf); + ((u8 *)images.ft_addr)[i] = (u8)(i & 0xff); + } + + ut_assertok(bootm_measure()); + + free(images.ft_addr); + free(initrd); + free(kernel); + + return 0; +} +MEASUREMENT_TEST(measure, 0); + +int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct unit_test *tests = UNIT_TEST_SUIT
Re: [PATCH v2 0/5] tpm: Support boot measurements
On 1/9/23 17:35, Heinrich Schuchardt wrote: On 1/9/23 22:55, Eddie James wrote: This series adds support for measuring the boot images more generically than the existing EFI support. Several EFI functions have been moved to the TPM layer. The series includes optional measurement from the bootm command. A new test case has been added for the bootm measurement to test the new path, and the sandbox TPM2 driver has been updated to support this use case. Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions. - Add test case - Drop #ifdefs for bootm - Add devicetree measurement config option - Update sandbox TPM driver This looks like a useful feature to me. Some questions remain: How about the booti and bootz commands. Are they covered by the change? No, not yet. What are the consequences of your changes for UEFI FIT images (cf. CONFIG_BOOTM_EFI)? I suppose the image would be measured twice, but only if the user selected both of the relevant config options. Eddie James (5): tpm: Fix spelling for tpmu_ha union tpm: Support boot measurements bootm: Support boot measurement tpm: sandbox: Update for needed TPM2 capabilities test: Add sandbox TPM boot measurement I am missing the documentation changes. These should describe which changes in the device-tree and in the configuration are needed to enable measurements. This should be in doc/usage/ Sure. Thanks, Eddie @Ilias: Could you contribute the UEFI part for the document, please. Best regards Heinrich arch/sandbox/dts/test.dts | 12 + boot/Kconfig | 23 ++ boot/bootm.c | 64 +++ cmd/bootm.c | 2 + configs/sandbox_defconfig | 1 + drivers/tpm/tpm2_tis_sandbox.c | 100 +++-- include/bootm.h | 2 + include/efi_tcg2.h | 44 -- include/image.h | 1 + include/test/suites.h | 1 + include/tpm-v2.h | 215 +- lib/efi_loader/efi_tcg2.c | 362 + lib/tpm-v2.c | 708 + test/boot/Makefile | 1 + test/boot/measurement.c | 66 +++ test/cmd_ut.c | 2 + 16 files changed, 1187 insertions(+), 417 deletions(-) create mode 100644 test/boot/measurement.c
Re: [PATCH v2 5/5] test: Add sandbox TPM boot measurement
On 1/10/23 16:02, Heinrich Schuchardt wrote: On 1/10/23 17:38, Eddie James wrote: On 1/9/23 17:26, Heinrich Schuchardt wrote: On 1/10/23 00:13, Heinrich Schuchardt wrote: On 1/9/23 22:55, Eddie James wrote: Use the sandbox TPM driver to measure some boot images in a unit test case. $ ./u-boot -T -c "ut measurement" Running 1 measurement tests Test: measure: measurement.c Failures: 0 Signed-off-by: Eddie James --- arch/sandbox/dts/test.dts | 12 +++ configs/sandbox_defconfig | 1 + include/test/suites.h | 1 + test/boot/Makefile | 1 + test/boot/measurement.c | 66 +++ test/cmd_ut.c | 2 ++ 6 files changed, 83 insertions(+) create mode 100644 test/boot/measurement.c diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index dffe10adbf..ad90bf0541 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -66,6 +66,17 @@ osd0 = "/osd"; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log@d0e000 { + no-map; + reg = <0x00d0e000 0x2000>; How should this work if you don't define linux,sml-base and linux,sml-size? I have sent a patch to the linux list for using a reserved memory region, as I have also added in the u-boot TPM layer for the event log. https://patchwork.kernel.org/project/linux-integrity/patch/20230103162010.381214-1-eaja...@linux.ibm.com/ Thank you for the clarification. The kernel patch seems to need rework: https://lore.kernel.org/all/202301040834.ysmhdmpw-...@intel.com/ Yes I'll address that. Shouldn't the sandbox device-tree support these properties? This will allow us to write a test application that the sandbox can run via booti/bootz (depending on bitness) and bootm. This test application can retrieve the event log and print it via Linux system calls. OK, I can add it to the main sandbox device-tree as well then. It is added to the sandbox test device-tree, used by the unit test case I added. Thanks, Eddie Best regards Heinrich
Re: [PATCH 3/3] bootm: Support boot measurement
On 1/4/23 03:56, Etienne Carriere wrote: Hello Eddie and all, On Tue, 3 Jan 2023 at 21:42, Eddie James wrote: Add a configuration option to measure the boot through the bootm function. Signed-off-by: Eddie James --- boot/bootm.c| 53 + cmd/bootm.c | 2 ++ common/Kconfig | 6 ++ include/image.h | 1 + 4 files changed, 62 insertions(+) diff --git a/boot/bootm.c b/boot/bootm.c index a4c0870c0f..7f64d79035 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -22,6 +22,9 @@ #include #include #include +#if defined(CONFIG_MEASURED_BOOT) +#include +#endif #if defined(CONFIG_CMD_USB) #include #endif @@ -713,6 +716,56 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc, if (!ret && (states & BOOTM_STATE_FINDOTHER)) ret = bootm_find_other(cmdtp, flag, argc, argv); +#if defined(CONFIG_MEASURED_BOOT) + if (!ret && (states & BOOTM_STATE_MEASURE)) { + void *initrd_buf; + void *image_buf; + const char *s; + u32 rd_len; + + ret = tcg2_measurement_init(); + if (ret) + goto measure_err; + + image_buf = map_sysmem(images->os.image_start, + images->os.image_len); + ret = tcg2_measure_data(8, images->os.image_len, image_buf, + EV_COMPACT_HASH, strlen("linux") + 1, + (u8 *)"linux"); + if (ret) + goto unmap_image; + + rd_len = images->rd_end - images->rd_start; + initrd_buf = map_sysmem(images->rd_start, rd_len); + ret = tcg2_measure_data(8, rd_len, initrd_buf, EV_COMPACT_HASH, + strlen("initrd") + 1, (u8 *)"initrd"); + if (ret) + goto unmap_initrd; + + ret = tcg2_measure_data(9, images->ft_len, + (u8 *)images->ft_addr, + EV_TABLE_OF_DEVICES, strlen("dts") + 1, + (u8 *)"dts"); This unconditionally measures DTB content but maybe there are information that may differ at each boot as a random MAC address or an ASLR seed. Do you think something should condition measurement of the passed DTB as proposed using a config switch in [1]? [1] https://lore.kernel.org/all/20221207151110.529106-1-etienne.carri...@linaro.org/ That would make sense, I am happy to add that in v2. Should I use that config switch as-is or add a new one for the bootm measurement? Thanks Eddie Regards, Etienne + if (ret) + goto unmap_initrd; + + s = env_get("bootargs"); + if (!s) + s = ""; + tcg2_measure_data(1, strlen(s) + 1, (u8 *)s, + EV_PLATFORM_CONFIG_FLAGS, strlen(s) + 1, + (u8 *)s); + +unmap_initrd: + unmap_sysmem(initrd_buf); +unmap_image: + unmap_sysmem(image_buf); + tcg2_measurement_term(); +measure_err: + ret = 0; + } +#endif + /* Load the OS */ if (!ret && (states & BOOTM_STATE_LOADOS)) { iflag = bootm_disable_interrupts(); diff --git a/cmd/bootm.c b/cmd/bootm.c index 37c2af96e0..0c4a713e02 100644 --- a/cmd/bootm.c +++ b/cmd/bootm.c @@ -161,6 +161,8 @@ int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) BOOTM_STATE_OS_GO; if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH)) states |= BOOTM_STATE_RAMDISK; + if (IS_ENABLED(CONFIG_MEASURED_BOOT)) + states |= BOOTM_STATE_MEASURE; if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS)) states |= BOOTM_STATE_OS_CMDLINE; ret = do_bootm_states(cmdtp, flag, argc, argv, states, , 1); diff --git a/common/Kconfig b/common/Kconfig index 21434c5cf1..57ef68e4f3 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -799,6 +799,12 @@ config AVB_BUF_SIZE endif # AVB_VERIFY +config MEASURED_BOOT + bool "Measure the boot to TPM and event log" + depends on HASH && TPM_V2 + help + This option enables measurement of the boot process. + config SCP03 bool "Build SCP03 - Secure Channel Protocol O3 - controls" depends on OPTEE || SANDBOX diff --git a/include/image.h b/include/image.h index 6f21dafba8..b00803eeac 100644 --- a/include/image.h +++ b/include/image.h @@ -406,6 +406,7 @@ struct bootm_headers { #define BOOTM_STATE_OS_FAKE_GO 0x0200 /* 'Almost' run the
Re: [PATCH 0/3] tpm: Support boot measurements
On 1/4/23 01:47, Ilias Apalodimas wrote: Hi Eddie, Thanks for the patch Looking at the patch there's a lot of code duplication with lib/efi_loader/efi_tcg2.c. Any reason why we aren't reusing that ? Hi, Well the EFI code can't be used directly without configuring to include the EFI subsystem and exporting a bunch of those functions in a header file somewhere, so I added the functions in the generic tpm librrary. Now it's a matter of doing the work to use the generic functions in the EFI system. I can do that in this series if necesssary, I just haven't gotten to it. Thanks, Eddie Regards /Ilias On Tue, 3 Jan 2023 at 22:42, Eddie James wrote: This series adds support for measuring the boot images more generically than the existing EFI support. The series includes optional measurement from the bootm command. Eventually the EFI code could be refactored to use the generic functions. Eddie James (3): tpm: Fix spelling for tpmu_ha union tpm: Support boot measurements bootm: Support boot measurement boot/bootm.c | 53 cmd/bootm.c| 2 + common/Kconfig | 6 + include/efi_tcg2.h | 44 --- include/image.h| 1 + include/tpm-v2.h | 139 - lib/tpm-v2.c | 700 + 7 files changed, 899 insertions(+), 46 deletions(-) -- 2.31.1
[PATCH v3 1/6] tpm: Fix spelling for tpmu_ha union
tmpu -> tpmu Signed-off-by: Eddie James Reviewed-by: Ilias Apalodimas --- include/tpm-v2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 737e57551d..85feda3e06 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -167,7 +167,7 @@ struct tcg_pcr_event { /** * Definition of TPMU_HA Union */ -union tmpu_ha { +union tpmu_ha { u8 sha1[TPM2_SHA1_DIGEST_SIZE]; u8 sha256[TPM2_SHA256_DIGEST_SIZE]; u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE]; @@ -183,7 +183,7 @@ union tmpu_ha { */ struct tpmt_ha { u16 hash_alg; - union tmpu_ha digest; + union tpmu_ha digest; } __packed; /** -- 2.31.1
[PATCH v3 6/6] doc: Add measured boot documentation
Briefly describe the feature and specify the requirements. Signed-off-by: Eddie James --- doc/usage/index.rst | 1 + doc/usage/measured_boot.rst | 23 +++ 2 files changed, 24 insertions(+) create mode 100644 doc/usage/measured_boot.rst diff --git a/doc/usage/index.rst b/doc/usage/index.rst index bbd40a6e18..cf2cd81966 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -12,6 +12,7 @@ Use U-Boot partitions cmdline semihosting + measured_boot Shell commands -- diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst new file mode 100644 index 00..13fd42a2fb --- /dev/null +++ b/doc/usage/measured_boot.rst @@ -0,0 +1,23 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Measured Boot += + +U-Boot can perform a measured boot, the process of hashing various components +of the boot process, extending the results in the TPM and logging the +component's measurement in memory for the operating system to consume. + +Requirements +- + +A hardware TPM 2.0 supported by the U-Boot drivers +CONFIG_TPM=y +CONFIG_MEASURED_BOOT=y +Device-tree configuration of the TPM device to specify the memory area +for event logging. The TPM device node must either contain a phandle to +a reserved memory region or "linux,sml-base" and "linux,sml-size" +indicating the address and size of the memory region. An example can be +found in arch/sandbox/dts/test.dts +The operating system must also be configured to use the memory regions +specified in the U-Boot device-tree in order to make use of the event +log. -- 2.31.1
[PATCH v3 3/6] bootm: Support boot measurement
Add a configuration option to measure the boot through the bootm function. Add the measurement state to the booti and bootz paths as well. Signed-off-by: Eddie James --- boot/Kconfig| 23 boot/bootm.c| 70 + cmd/booti.c | 1 + cmd/bootm.c | 2 ++ cmd/bootz.c | 1 + include/bootm.h | 2 ++ include/image.h | 1 + 7 files changed, 100 insertions(+) diff --git a/boot/Kconfig b/boot/Kconfig index 30bc182fcd..e90d61412e 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -587,6 +587,29 @@ config LEGACY_IMAGE_FORMAT loaded. If a board needs the legacy image format support in this case, enable it here. +config MEASURED_BOOT + bool "Measure boot images and configuration to TPM and event log" + depends on HASH && TPM_V2 + help + This option enables measurement of the boot process. Measurement + involves creating cryptographic hashes of the binary images that + are booting and storing them in the TPM. In addition, a log of + these hashes is stored in memory for the OS to verify the booted + images and configuration. Enable this if the OS has configured + some memory area for the event log and you intend to use some + attestation tools on your system. + +if MEASURED_BOOT + config MEASURE_DEVICETREE + bool "Measure the devicetree image" + default y if MEASURED_BOOT + help + On some platforms, the devicetree is not static as it may contain + random MAC addresses or other such data that changes each boot. + Therefore, it should not be measured into the TPM. In that case, + disable the measurement here. +endif # MEASURED_BOOT + config SUPPORT_RAW_INITRD bool "Enable raw initrd images" help diff --git a/boot/bootm.c b/boot/bootm.c index 15fce8ad95..c8423f2c60 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -22,6 +22,7 @@ #include #include #include +#include #if defined(CONFIG_CMD_USB) #include #endif @@ -659,6 +660,72 @@ int bootm_process_cmdline_env(int flags) return 0; } +int bootm_measure(struct bootm_headers *images) +{ + int ret = 0; + + /* Skip measurement if EFI is going to do it */ + if (images->os.os == IH_OS_EFI && + IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL) && + IS_ENABLED(CONFIG_BOOTM_EFI)) + return ret; + + if (IS_ENABLED(CONFIG_MEASURED_BOOT)) { + struct tcg2_event_log elog; + struct udevice *dev; + void *initrd_buf; + void *image_buf; + const char *s; + u32 rd_len; + + ret = tcg2_measurement_init(, ); + if (ret) + return ret; + + image_buf = map_sysmem(images->os.image_start, + images->os.image_len); + ret = tcg2_measure_data(dev, , 8, images->os.image_len, + image_buf, EV_COMPACT_HASH, + strlen("linux") + 1, (u8 *)"linux"); + if (ret) + goto unmap_image; + + rd_len = images->rd_end - images->rd_start; + initrd_buf = map_sysmem(images->rd_start, rd_len); + ret = tcg2_measure_data(dev, , 8, rd_len, initrd_buf, + EV_COMPACT_HASH, strlen("initrd") + 1, + (u8 *)"initrd"); + if (ret) + goto unmap_initrd; + + if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) { + ret = tcg2_measure_data(dev, , 9, images->ft_len, + (u8 *)images->ft_addr, + EV_TABLE_OF_DEVICES, + strlen("dts") + 1, + (u8 *)"dts"); + if (ret) + goto unmap_initrd; + } + + s = env_get("bootargs"); + if (!s) + s = ""; + ret = tcg2_measure_data(dev, , 1, strlen(s) + 1, (u8 *)s, + EV_PLATFORM_CONFIG_FLAGS, + strlen(s) + 1, (u8 *)s); + +unmap_initrd: + unmap_sysmem(initrd_buf); + +unmap_image: + unmap_sysmem(image_buf); + tcg2_measurement_term(dev, , ret != 0); + } + + return ret; +} + /** * Execute selected states of the bootm command. * @@ -710,6 +777,9 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc, if (!ret &&
[PATCH v3 5/6] test: Add sandbox TPM boot measurement
Use the sandbox TPM driver to measure some boot images in a unit test case. Signed-off-by: Eddie James --- arch/sandbox/dts/sandbox.dtsi | 14 arch/sandbox/dts/test.dts | 13 +++ configs/sandbox_defconfig | 1 + include/test/suites.h | 1 + test/boot/Makefile| 1 + test/boot/measurement.c | 66 +++ test/cmd_ut.c | 2 ++ 7 files changed, 98 insertions(+) create mode 100644 test/boot/measurement.c diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index afe598a4f5..eb9df8f4e3 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -4,9 +4,22 @@ * and sandbox64 builds. */ +#include + #define USB_CLASS_HUB 9 / { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman { }; @@ -345,6 +358,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; triangle { diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index dffe10adbf..920d4de140 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -9,6 +9,7 @@ /dts-v1/; +#include #include #include #include @@ -66,6 +67,17 @@ osd0 = "/osd"; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman: binman { }; @@ -1332,6 +1344,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; uart0: serial { diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index de799b5cea..5ac115f2d8 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -335,3 +335,4 @@ CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +CONFIG_MEASURED_BOOT=y diff --git a/include/test/suites.h b/include/test/suites.h index 9ce49cbb03..4c284bbeaa 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -44,6 +44,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); +int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/test/boot/Makefile b/test/boot/Makefile index d724629d3b..24cc20bdff 100644 --- a/test/boot/Makefile +++ b/test/boot/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o obj-$(CONFIG_FIT) += image.o +obj-$(CONFIG_MEASURED_BOOT) += measurement.o ifdef CONFIG_OF_LIVE obj-$(CONFIG_BOOTMETH_VBE_SIMPLE) += vbe_simple.o diff --git a/test/boot/measurement.c b/test/boot/measurement.c new file mode 100644 index 00..2155208894 --- /dev/null +++ b/test/boot/measurement.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for measured boot functions + * + * Copyright 2023 IBM Corp. + * Written by Eddie James + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MEASUREMENT_TEST(_name, _flags)\ + UNIT_TEST(_name, _flags, measurement_test) + +static int measure(struct unit_test_state *uts) +{ + struct bootm_headers images; + const size_t size = 1024; + u8 *kernel; + u8 *initrd; + size_t i; + + kernel = malloc(size); + initrd = malloc(size); + + images.os.image_start = map_to_sysmem(kernel); + images.os.image_len = size; + + images.rd_start = map_to_sysmem(initrd); + images.rd_end = images.rd_start + size; + + images.ft_addr = malloc(size); + images.ft_len = size; + + env_set("bootargs", "measurement testing"); + + for (i = 0; i < size; ++i) { + kernel[i] = (u8)(0xf0 | (i & 0xf)); + initrd[i] = (u8)((i & 0xf0) | 0xf); + ((u8 *)images.ft_addr)[i] = (u8)(i & 0xff); + } + + ut_assertok(bootm_measure()); + +
[PATCH v3 4/6] tpm: sandbox: Update for needed TPM2 capabilities
The driver needs to support getting the PCRs in the capabilities command. Fix various other things and support the max number of PCRs for TPM2. Signed-off-by: Eddie James Reviewed-by: Simon Glass --- drivers/tpm/tpm2_tis_sandbox.c | 100 - 1 file changed, 72 insertions(+), 28 deletions(-) diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c index dd94bdc31f..ea7fb5e3cb 100644 --- a/drivers/tpm/tpm2_tis_sandbox.c +++ b/drivers/tpm/tpm2_tis_sandbox.c @@ -22,11 +22,6 @@ enum tpm2_hierarchy { TPM2_HIERARCHY_NB, }; -/* Subset of supported capabilities */ -enum tpm2_capability { - TPM_CAP_TPM_PROPERTIES = 0x6, -}; - /* Subset of supported properties */ #define TPM2_PROPERTIES_OFFSET 0x020E @@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property { TPM2_PROPERTY_NB, }; -#define SANDBOX_TPM_PCR_NB 1 +#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS +#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8) /* * Information about our TPM emulation. This is preserved in the sandbox @@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, int i, j; /* TPM2_GetProperty */ - u32 capability, property, property_count; + u32 capability, property, property_count, val; /* TPM2_PCR_Read/Extend variables */ int pcr_index = 0; @@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, case TPM2_CC_GET_CAPABILITY: capability = get_unaligned_be32(sent); sent += sizeof(capability); - if (capability != TPM_CAP_TPM_PROPERTIES) { - printf("Sandbox TPM only support TPM_CAPABILITIES\n"); - return TPM2_RC_HANDLE; - } - property = get_unaligned_be32(sent); sent += sizeof(property); - property -= TPM2_PROPERTIES_OFFSET; - property_count = get_unaligned_be32(sent); sent += sizeof(property_count); - if (!property_count || - property + property_count > TPM2_PROPERTY_NB) { + + switch (capability) { + case TPM2_CAP_PCRS: + break; + case TPM2_CAP_TPM_PROPERTIES: + if (!property_count) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + + if (property > TPM2_PROPERTIES_OFFSET && + ((property - TPM2_PROPERTIES_OFFSET) + +property_count > TPM2_PROPERTY_NB)) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + break; + default: + printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or " + "TPM2_CAP_TPM_PROPERTIES\n"); rc = TPM2_RC_HANDLE; return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); } @@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, put_unaligned_be32(capability, recv); recv += sizeof(capability); - /* Give the number of properties that follow */ - put_unaligned_be32(property_count, recv); - recv += sizeof(property_count); - - /* Fill with the properties */ - for (i = 0; i < property_count; i++) { - put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property + - i, recv); - recv += sizeof(property); - put_unaligned_be32(tpm->properties[property + i], - recv); - recv += sizeof(property); + switch (capability) { + case TPM2_CAP_PCRS: + /* Give the number of algorithms supported - just SHA256 */ + put_unaligned_be32(1, recv); + recv += sizeof(u32); + + /* Give SHA256 algorithm */ + put_unaligned_be16(TPM2_ALG_SHA256, recv); + recv += sizeof(u16); + + /* Select the PCRs supported */ + *recv = SANDBOX_TPM_PCR_SELECT_MAX; + recv++; + + /* Activate all the PCR bits */ + for (i = 0; i < SANDBOX_TPM_PCR_SELECT_
[PATCH v3 0/6] tpm: Support boot measurements
This series adds support for measuring the boot images more generically than the existing EFI support. Several EFI functions have been moved to the TPM layer. The series includes optional measurement from the bootm command. A new test case has been added for the bootm measurement to test the new path, and the sandbox TPM2 driver has been updated to support this use case. Changes since v2: - Add documentation. - Changed reserved memory address to the top of the RAM for sandbox dts. - Add measure state to booti and bootz. - Skip measurement for EFI images that should be measured Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions. - Add test case - Drop #ifdefs for bootm - Add devicetree measurement config option - Update sandbox TPM driver Eddie James (6): tpm: Fix spelling for tpmu_ha union tpm: Support boot measurements bootm: Support boot measurement tpm: sandbox: Update for needed TPM2 capabilities test: Add sandbox TPM boot measurement doc: Add measured boot documentation arch/sandbox/dts/sandbox.dtsi | 14 + arch/sandbox/dts/test.dts | 13 + boot/Kconfig | 23 ++ boot/bootm.c | 70 cmd/booti.c| 1 + cmd/bootm.c| 2 + cmd/bootz.c| 1 + configs/sandbox_defconfig | 1 + doc/usage/index.rst| 1 + doc/usage/measured_boot.rst| 23 ++ drivers/tpm/tpm2_tis_sandbox.c | 100 +++-- include/bootm.h| 2 + include/efi_tcg2.h | 44 -- include/image.h| 1 + include/test/suites.h | 1 + include/tpm-v2.h | 215 +- lib/efi_loader/efi_tcg2.c | 362 + lib/tpm-v2.c | 708 + test/boot/Makefile | 1 + test/boot/measurement.c| 66 +++ test/cmd_ut.c | 2 + 21 files changed, 1234 insertions(+), 417 deletions(-) create mode 100644 doc/usage/measured_boot.rst create mode 100644 test/boot/measurement.c -- 2.31.1
[PATCH v3 2/6] tpm: Support boot measurements
Add TPM2 functions to support boot measurement. This includes starting up the TPM, initializing/appending the event log, and measuring the U-Boot version. Much of the code was used in the EFI subsystem, so remove it there and use the common functions. Signed-off-by: Eddie James --- include/efi_tcg2.h| 44 --- include/tpm-v2.h | 211 lib/efi_loader/efi_tcg2.c | 362 +-- lib/tpm-v2.c | 708 ++ 4 files changed, 938 insertions(+), 387 deletions(-) diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h index 874306dc11..23016773f4 100644 --- a/include/efi_tcg2.h +++ b/include/efi_tcg2.h @@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability { #define BOOT_SERVICE_CAPABILITY_MIN \ offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks) -#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03" -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2 - -/** - * struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information - * - * @algorithm_id: algorithm defined in enum tpm2_algorithms - * @digest_size: size of the algorithm - */ -struct tcg_efi_spec_id_event_algorithm_size { - u16 algorithm_id; - u16 digest_size; -} __packed; - -/** - * struct TCG_EfiSpecIDEventStruct - content of the event log header - * - * @signature: signature, set to Spec ID Event03 - * @platform_class:class defined in TCG ACPI Specification - * Client Common Header. - * @spec_version_minor:minor version - * @spec_version_major:major version - * @spec_version_errata: major version - * @uintn_size:size of the efi_uintn_t fields used in various - * data structures used in this specification. - * 0x01 indicates u32 and 0x02 indicates u64 - * @number_of_algorithms: hashing algorithms used in this event log - * @digest_sizes: array of number_of_algorithms pairs - * 1st member defines the algorithm id - * 2nd member defines the algorithm size - */ -struct tcg_efi_spec_id_event { - u8 signature[16]; - u32 platform_class; - u8 spec_version_minor; - u8 spec_version_major; - u8 spec_errata; - u8 uintn_size; - u32 number_of_algorithms; - struct tcg_efi_spec_id_event_algorithm_size digest_sizes[]; -} __packed; - /** * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log * @version: version number for this structure diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 85feda3e06..e3db3419dd 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -214,6 +214,50 @@ struct tcg_pcr_event2 { u8 event[]; } __packed; +/** + * struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information + * + * @algorithm_id: algorithm defined in enum tpm2_algorithms + * @digest_size: size of the algorithm + */ +struct tcg_efi_spec_id_event_algorithm_size { + u16 algorithm_id; + u16 digest_size; +} __packed; + +#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03" +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2 +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0 +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2 + +/** + * struct TCG_EfiSpecIDEventStruct - content of the event log header + * + * @signature: signature, set to Spec ID Event03 + * @platform_class:class defined in TCG ACPI Specification + * Client Common Header. + * @spec_version_minor:minor version + * @spec_version_major:major version + * @spec_version_errata: major version + * @uintn_size:size of the efi_uintn_t fields used in various + * data structures used in this specification. + * 0x01 indicates u32 and 0x02 indicates u64 + * @number_of_algorithms: hashing algorithms used in this event log + * @digest_sizes: array of number_of_algorithms pairs + * 1st member defines the algorithm id + * 2nd member defines the algorithm size + */ +struct tcg_efi_spec_id_event { + u8 signature[16]; + u32 platform_class; + u8 spec_version_minor; + u8 spec_version_major; + u8 spec_errata; + u8 uintn_size; + u32 number_of_algorithms; + struct tcg_efi_spec_id_event_algorithm_size digest_sizes[]; +} __packed; + /** * TPM2 Structure Tags for command/response buffers. * @@ -340,6 +384,24 @@ enum tpm2_algorithms {
Re: [PATCH v3 2/6] tpm: Support boot measurements
On 1/12/23 17:43, Simon Glass wrote: Hi Eddie, On Thu, 12 Jan 2023 at 09:16, Eddie James wrote: Add TPM2 functions to support boot measurement. This includes starting up the TPM, initializing/appending the event log, and measuring the U-Boot version. Much of the code was used in the EFI subsystem, so remove it there and use the common functions. Signed-off-by: Eddie James --- include/efi_tcg2.h| 44 --- include/tpm-v2.h | 211 lib/efi_loader/efi_tcg2.c | 362 +-- lib/tpm-v2.c | 708 ++ 4 files changed, 938 insertions(+), 387 deletions(-) [..] diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c index 697b982e07..00e1b04d74 100644 --- a/lib/tpm-v2.c +++ b/lib/tpm-v2.c @@ -4,13 +4,597 @@ * Author: Miquel Raynal */ +#include +#include Please check header order: https://u-boot.readthedocs.io/en/latest/develop/codingstyle.html#include-files Sure, however I did have a compile error with sandbox build due to missing phys_addr_t definition in asm/io.h... #include #include +#include #include #include #include +#include +#include +#include +#include +#include +#include +#include #include "tpm-utils.h" [..] +static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log *elog) +{ + struct tcg_efi_spec_id_event *ev; We cannot add EFI things to generic TPM code. Ah, this is NOT an EFI thing even though it is named as such. Please see https://trustedcomputinggroup.org/wp-content/uploads/TCG_ServerManagDomainFWProfile_r1p00_pub.pdf section 9 and https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_Specific_Platform_Profile_for_TPM_2p0_1p04_PUBLIC.pdf section 9 Neither of these documents are specific to EFI. + struct tcg_pcr_event *log; + u32 event_size; + u32 count = 0; + u32 log_size; + u32 active; + u32 mask; + size_t i; + u16 len; + int rc; + + rc = tcg2_get_active_pcr_banks(dev, ); + if (rc) + return rc; + + event_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes); + for (i = 0; i < ARRAY_SIZE(tcg2algos); ++i) { + mask = tpm2_algorithm_to_mask(tcg2algos[i]); + + if (!(active & mask)) + continue; + + switch (tcg2algos[i]) { + case TPM2_ALG_SHA1: + case TPM2_ALG_SHA256: + case TPM2_ALG_SHA384: + case TPM2_ALG_SHA512: + count++; + break; + default: + continue; + } + } + + event_size += 1 + + (sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count); + log_size = offsetof(struct tcg_pcr_event, event) + event_size; + + if (log_size > elog->log_size) { + printf("%s: log too large: %u > %u\n", __func__, log_size, + elog->log_size); + return -ENOBUFS; + } + + log = (struct tcg_pcr_event *)elog->log; + put_unaligned_le32(0, >pcr_index); + put_unaligned_le32(EV_NO_ACTION, >event_type); + memset(>digest, 0, sizeof(log->digest)); + put_unaligned_le32(event_size, >event_size); + + ev = (struct tcg_efi_spec_id_event *)log->event; + strlcpy((char *)ev->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03, Same with all of this. + sizeof(ev->signature)); + put_unaligned_le32(0, >platform_class); + ev->spec_version_minor = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2; + ev->spec_version_major = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2; + ev->spec_errata = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2; I'm not quite sure what is going on here...is this log in a format defined by the EFI spec? What if we are not using EFI? How would a different format be used? Put another way, people using a TPM should not pull in EFI things just to do that. Agreed, however the EFI spec is not involved. These specifications and structures are general to any boot measurement. I would guess EFI was the first to do this and therefore defined some structures that the TCG re-used when writing the specs. I'm just not quite sure of the best approach here... Regards, Simon
[PATCH v2 3/5] bootm: Support boot measurement
Add a configuration option to measure the boot through the bootm function. Signed-off-by: Eddie James --- boot/Kconfig| 23 ++ boot/bootm.c| 64 + cmd/bootm.c | 2 ++ include/bootm.h | 2 ++ include/image.h | 1 + 5 files changed, 92 insertions(+) diff --git a/boot/Kconfig b/boot/Kconfig index 30bc182fcd..e90d61412e 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -587,6 +587,29 @@ config LEGACY_IMAGE_FORMAT loaded. If a board needs the legacy image format support in this case, enable it here. +config MEASURED_BOOT + bool "Measure boot images and configuration to TPM and event log" + depends on HASH && TPM_V2 + help + This option enables measurement of the boot process. Measurement + involves creating cryptographic hashes of the binary images that + are booting and storing them in the TPM. In addition, a log of + these hashes is stored in memory for the OS to verify the booted + images and configuration. Enable this if the OS has configured + some memory area for the event log and you intend to use some + attestation tools on your system. + +if MEASURED_BOOT + config MEASURE_DEVICETREE + bool "Measure the devicetree image" + default y if MEASURED_BOOT + help + On some platforms, the devicetree is not static as it may contain + random MAC addresses or other such data that changes each boot. + Therefore, it should not be measured into the TPM. In that case, + disable the measurement here. +endif # MEASURED_BOOT + config SUPPORT_RAW_INITRD bool "Enable raw initrd images" help diff --git a/boot/bootm.c b/boot/bootm.c index 15fce8ad95..932961ceb7 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -22,6 +22,7 @@ #include #include #include +#include #if defined(CONFIG_CMD_USB) #include #endif @@ -659,6 +660,66 @@ int bootm_process_cmdline_env(int flags) return 0; } +int bootm_measure(struct bootm_headers *images) +{ + int ret = 0; + + if (IS_ENABLED(CONFIG_MEASURED_BOOT)) { + struct tcg2_event_log elog; + struct udevice *dev; + void *initrd_buf; + void *image_buf; + const char *s; + u32 rd_len; + + ret = tcg2_measurement_init(, ); + if (ret) + return ret; + + image_buf = map_sysmem(images->os.image_start, + images->os.image_len); + ret = tcg2_measure_data(dev, , 8, images->os.image_len, + image_buf, EV_COMPACT_HASH, + strlen("linux") + 1, (u8 *)"linux"); + if (ret) + goto unmap_image; + + rd_len = images->rd_end - images->rd_start; + initrd_buf = map_sysmem(images->rd_start, rd_len); + ret = tcg2_measure_data(dev, , 8, rd_len, initrd_buf, + EV_COMPACT_HASH, strlen("initrd") + 1, + (u8 *)"initrd"); + if (ret) + goto unmap_initrd; + + if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) { + ret = tcg2_measure_data(dev, , 9, images->ft_len, + (u8 *)images->ft_addr, + EV_TABLE_OF_DEVICES, + strlen("dts") + 1, + (u8 *)"dts"); + if (ret) + goto unmap_initrd; + } + + s = env_get("bootargs"); + if (!s) + s = ""; + ret = tcg2_measure_data(dev, , 1, strlen(s) + 1, (u8 *)s, + EV_PLATFORM_CONFIG_FLAGS, + strlen(s) + 1, (u8 *)s); + +unmap_initrd: + unmap_sysmem(initrd_buf); + +unmap_image: + unmap_sysmem(image_buf); + tcg2_measurement_term(dev, , ret != 0); + } + + return ret; +} + /** * Execute selected states of the bootm command. * @@ -710,6 +771,9 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc, if (!ret && (states & BOOTM_STATE_FINDOTHER)) ret = bootm_find_other(cmdtp, flag, argc, argv); + if (IS_ENABLED(CONFIG_MEASURED_BOOT) && !ret && (states & BOOTM_STATE_MEASURE)) + bootm_measure(images); + /* Load the OS */ if (!ret && (states & BOOTM_STATE_LOADOS)) {
[PATCH v2 4/5] tpm: sandbox: Update for needed TPM2 capabilities
The driver needs to support getting the PCRs in the capabilities command. Fix various other things and support the max number of PCRs for TPM2. Signed-off-by: Eddie James --- drivers/tpm/tpm2_tis_sandbox.c | 100 - 1 file changed, 72 insertions(+), 28 deletions(-) diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c index dd94bdc31f..ea7fb5e3cb 100644 --- a/drivers/tpm/tpm2_tis_sandbox.c +++ b/drivers/tpm/tpm2_tis_sandbox.c @@ -22,11 +22,6 @@ enum tpm2_hierarchy { TPM2_HIERARCHY_NB, }; -/* Subset of supported capabilities */ -enum tpm2_capability { - TPM_CAP_TPM_PROPERTIES = 0x6, -}; - /* Subset of supported properties */ #define TPM2_PROPERTIES_OFFSET 0x020E @@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property { TPM2_PROPERTY_NB, }; -#define SANDBOX_TPM_PCR_NB 1 +#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS +#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8) /* * Information about our TPM emulation. This is preserved in the sandbox @@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, int i, j; /* TPM2_GetProperty */ - u32 capability, property, property_count; + u32 capability, property, property_count, val; /* TPM2_PCR_Read/Extend variables */ int pcr_index = 0; @@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, case TPM2_CC_GET_CAPABILITY: capability = get_unaligned_be32(sent); sent += sizeof(capability); - if (capability != TPM_CAP_TPM_PROPERTIES) { - printf("Sandbox TPM only support TPM_CAPABILITIES\n"); - return TPM2_RC_HANDLE; - } - property = get_unaligned_be32(sent); sent += sizeof(property); - property -= TPM2_PROPERTIES_OFFSET; - property_count = get_unaligned_be32(sent); sent += sizeof(property_count); - if (!property_count || - property + property_count > TPM2_PROPERTY_NB) { + + switch (capability) { + case TPM2_CAP_PCRS: + break; + case TPM2_CAP_TPM_PROPERTIES: + if (!property_count) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + + if (property > TPM2_PROPERTIES_OFFSET && + ((property - TPM2_PROPERTIES_OFFSET) + +property_count > TPM2_PROPERTY_NB)) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + break; + default: + printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or " + "TPM2_CAP_TPM_PROPERTIES\n"); rc = TPM2_RC_HANDLE; return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); } @@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, put_unaligned_be32(capability, recv); recv += sizeof(capability); - /* Give the number of properties that follow */ - put_unaligned_be32(property_count, recv); - recv += sizeof(property_count); - - /* Fill with the properties */ - for (i = 0; i < property_count; i++) { - put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property + - i, recv); - recv += sizeof(property); - put_unaligned_be32(tpm->properties[property + i], - recv); - recv += sizeof(property); + switch (capability) { + case TPM2_CAP_PCRS: + /* Give the number of algorithms supported - just SHA256 */ + put_unaligned_be32(1, recv); + recv += sizeof(u32); + + /* Give SHA256 algorithm */ + put_unaligned_be16(TPM2_ALG_SHA256, recv); + recv += sizeof(u16); + + /* Select the PCRs supported */ + *recv = SANDBOX_TPM_PCR_SELECT_MAX; + recv++; + + /* Activate all the PCR bits */ + for (i = 0; i < SANDBOX_TPM_PCR_SELECT_MAX; ++i) { +
[PATCH v2 1/5] tpm: Fix spelling for tpmu_ha union
tmpu -> tpmu Signed-off-by: Eddie James Reviewed-by: Ilias Apalodimas --- include/tpm-v2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 737e57551d..85feda3e06 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -167,7 +167,7 @@ struct tcg_pcr_event { /** * Definition of TPMU_HA Union */ -union tmpu_ha { +union tpmu_ha { u8 sha1[TPM2_SHA1_DIGEST_SIZE]; u8 sha256[TPM2_SHA256_DIGEST_SIZE]; u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE]; @@ -183,7 +183,7 @@ union tmpu_ha { */ struct tpmt_ha { u16 hash_alg; - union tmpu_ha digest; + union tpmu_ha digest; } __packed; /** -- 2.31.1
[PATCH v2 2/5] tpm: Support boot measurements
Add TPM2 functions to support boot measurement. This includes starting up the TPM, initializing/appending the event log, and measuring the U-Boot version. Much of the code was used in the EFI subsystem, so remove it there and use the common functions. Signed-off-by: Eddie James --- include/efi_tcg2.h| 44 --- include/tpm-v2.h | 211 lib/efi_loader/efi_tcg2.c | 362 +-- lib/tpm-v2.c | 708 ++ 4 files changed, 938 insertions(+), 387 deletions(-) diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h index 874306dc11..23016773f4 100644 --- a/include/efi_tcg2.h +++ b/include/efi_tcg2.h @@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability { #define BOOT_SERVICE_CAPABILITY_MIN \ offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks) -#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03" -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2 - -/** - * struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information - * - * @algorithm_id: algorithm defined in enum tpm2_algorithms - * @digest_size: size of the algorithm - */ -struct tcg_efi_spec_id_event_algorithm_size { - u16 algorithm_id; - u16 digest_size; -} __packed; - -/** - * struct TCG_EfiSpecIDEventStruct - content of the event log header - * - * @signature: signature, set to Spec ID Event03 - * @platform_class:class defined in TCG ACPI Specification - * Client Common Header. - * @spec_version_minor:minor version - * @spec_version_major:major version - * @spec_version_errata: major version - * @uintn_size:size of the efi_uintn_t fields used in various - * data structures used in this specification. - * 0x01 indicates u32 and 0x02 indicates u64 - * @number_of_algorithms: hashing algorithms used in this event log - * @digest_sizes: array of number_of_algorithms pairs - * 1st member defines the algorithm id - * 2nd member defines the algorithm size - */ -struct tcg_efi_spec_id_event { - u8 signature[16]; - u32 platform_class; - u8 spec_version_minor; - u8 spec_version_major; - u8 spec_errata; - u8 uintn_size; - u32 number_of_algorithms; - struct tcg_efi_spec_id_event_algorithm_size digest_sizes[]; -} __packed; - /** * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log * @version: version number for this structure diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 85feda3e06..e3db3419dd 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -214,6 +214,50 @@ struct tcg_pcr_event2 { u8 event[]; } __packed; +/** + * struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information + * + * @algorithm_id: algorithm defined in enum tpm2_algorithms + * @digest_size: size of the algorithm + */ +struct tcg_efi_spec_id_event_algorithm_size { + u16 algorithm_id; + u16 digest_size; +} __packed; + +#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03" +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2 +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0 +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2 + +/** + * struct TCG_EfiSpecIDEventStruct - content of the event log header + * + * @signature: signature, set to Spec ID Event03 + * @platform_class:class defined in TCG ACPI Specification + * Client Common Header. + * @spec_version_minor:minor version + * @spec_version_major:major version + * @spec_version_errata: major version + * @uintn_size:size of the efi_uintn_t fields used in various + * data structures used in this specification. + * 0x01 indicates u32 and 0x02 indicates u64 + * @number_of_algorithms: hashing algorithms used in this event log + * @digest_sizes: array of number_of_algorithms pairs + * 1st member defines the algorithm id + * 2nd member defines the algorithm size + */ +struct tcg_efi_spec_id_event { + u8 signature[16]; + u32 platform_class; + u8 spec_version_minor; + u8 spec_version_major; + u8 spec_errata; + u8 uintn_size; + u32 number_of_algorithms; + struct tcg_efi_spec_id_event_algorithm_size digest_sizes[]; +} __packed; + /** * TPM2 Structure Tags for command/response buffers. * @@ -340,6 +384,24 @@ enum tpm2_algorithms {
[PATCH v2 5/5] test: Add sandbox TPM boot measurement
Use the sandbox TPM driver to measure some boot images in a unit test case. $ ./u-boot -T -c "ut measurement" Running 1 measurement tests Test: measure: measurement.c Failures: 0 Signed-off-by: Eddie James --- arch/sandbox/dts/test.dts | 12 +++ configs/sandbox_defconfig | 1 + include/test/suites.h | 1 + test/boot/Makefile| 1 + test/boot/measurement.c | 66 +++ test/cmd_ut.c | 2 ++ 6 files changed, 83 insertions(+) create mode 100644 test/boot/measurement.c diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index dffe10adbf..ad90bf0541 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -66,6 +66,17 @@ osd0 = "/osd"; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log@d0e000 { + no-map; + reg = <0x00d0e000 0x2000>; + }; + }; + binman: binman { }; @@ -1332,6 +1343,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; uart0: serial { diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index de799b5cea..5ac115f2d8 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -335,3 +335,4 @@ CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +CONFIG_MEASURED_BOOT=y diff --git a/include/test/suites.h b/include/test/suites.h index a01000e127..f9284871b0 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -43,6 +43,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); +int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/test/boot/Makefile b/test/boot/Makefile index d724629d3b..24cc20bdff 100644 --- a/test/boot/Makefile +++ b/test/boot/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o obj-$(CONFIG_FIT) += image.o +obj-$(CONFIG_MEASURED_BOOT) += measurement.o ifdef CONFIG_OF_LIVE obj-$(CONFIG_BOOTMETH_VBE_SIMPLE) += vbe_simple.o diff --git a/test/boot/measurement.c b/test/boot/measurement.c new file mode 100644 index 00..2155208894 --- /dev/null +++ b/test/boot/measurement.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for measured boot functions + * + * Copyright 2023 IBM Corp. + * Written by Eddie James + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MEASUREMENT_TEST(_name, _flags)\ + UNIT_TEST(_name, _flags, measurement_test) + +static int measure(struct unit_test_state *uts) +{ + struct bootm_headers images; + const size_t size = 1024; + u8 *kernel; + u8 *initrd; + size_t i; + + kernel = malloc(size); + initrd = malloc(size); + + images.os.image_start = map_to_sysmem(kernel); + images.os.image_len = size; + + images.rd_start = map_to_sysmem(initrd); + images.rd_end = images.rd_start + size; + + images.ft_addr = malloc(size); + images.ft_len = size; + + env_set("bootargs", "measurement testing"); + + for (i = 0; i < size; ++i) { + kernel[i] = (u8)(0xf0 | (i & 0xf)); + initrd[i] = (u8)((i & 0xf0) | 0xf); + ((u8 *)images.ft_addr)[i] = (u8)(i & 0xff); + } + + ut_assertok(bootm_measure()); + + free(images.ft_addr); + free(initrd); + free(kernel); + + return 0; +} +MEASUREMENT_TEST(measure, 0); + +int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct unit_test *tests = UNIT_TEST_SUITE_START(measurement_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(measurement_test); + + return cmd_ut_category("measurement", "measurement_test_", tests, + n_ents, argc, argv); +} diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 2736582f11..819031c0f8 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -100,6 +100,8 @@ static struct cmd_tbl cmd_ut_sub[] = { "", ""), U_BOOT_CMD_MKENT(bloblist, CONFIG_SYS_MAXARGS, 1,
[PATCH v2 0/5] tpm: Support boot measurements
This series adds support for measuring the boot images more generically than the existing EFI support. Several EFI functions have been moved to the TPM layer. The series includes optional measurement from the bootm command. A new test case has been added for the bootm measurement to test the new path, and the sandbox TPM2 driver has been updated to support this use case. Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions. - Add test case - Drop #ifdefs for bootm - Add devicetree measurement config option - Update sandbox TPM driver Eddie James (5): tpm: Fix spelling for tpmu_ha union tpm: Support boot measurements bootm: Support boot measurement tpm: sandbox: Update for needed TPM2 capabilities test: Add sandbox TPM boot measurement arch/sandbox/dts/test.dts | 12 + boot/Kconfig | 23 ++ boot/bootm.c | 64 +++ cmd/bootm.c| 2 + configs/sandbox_defconfig | 1 + drivers/tpm/tpm2_tis_sandbox.c | 100 +++-- include/bootm.h| 2 + include/efi_tcg2.h | 44 -- include/image.h| 1 + include/test/suites.h | 1 + include/tpm-v2.h | 215 +- lib/efi_loader/efi_tcg2.c | 362 + lib/tpm-v2.c | 708 + test/boot/Makefile | 1 + test/boot/measurement.c| 66 +++ test/cmd_ut.c | 2 + 16 files changed, 1187 insertions(+), 417 deletions(-) create mode 100644 test/boot/measurement.c -- 2.31.1
Re: [PATCH v2 5/5] test: Add sandbox TPM boot measurement
On 1/10/23 16:37, Heinrich Schuchardt wrote: On 1/10/23 23:32, Heinrich Schuchardt wrote: On 1/9/23 22:55, Eddie James wrote: Use the sandbox TPM driver to measure some boot images in a unit test case. $ ./u-boot -T -c "ut measurement" Running 1 measurement tests Test: measure: measurement.c Failures: 0 Signed-off-by: Eddie James --- arch/sandbox/dts/test.dts | 12 +++ configs/sandbox_defconfig | 1 + include/test/suites.h | 1 + test/boot/Makefile | 1 + test/boot/measurement.c | 66 +++ test/cmd_ut.c | 2 ++ 6 files changed, 83 insertions(+) create mode 100644 test/boot/measurement.c diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index dffe10adbf..ad90bf0541 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -66,6 +66,17 @@ osd0 = "/osd"; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log@d0e000 { + no-map; Isn't no-map misplaced? Shouldn't it be a reserved-memory property? The placement is correct. But I still wonder why we should have this area as no-map. If the memory region is not mapped, Linux can never access it as described in Documentation/devicetree/bindings/reserved-memory/reserved-memory.yaml. I read the documentation as meaning that Linux won't map it as part of it's standard mappings. It's still available for a device driver (TPM driver in this case). I believe no-map is appropriate here since we don't want anything except the TPM driver to access that memory. Thanks, Eddie Please, document all changes to the device-tree semantics via patches for the Linux kernels documentation and provide a full example. Best regards Heinrich
[PATCH 2/3] tpm: Support boot measurements
Add TPM2 functions to support boot measurement. This includes starting up the TPM, initializing/appending the event log, and measuring the U-Boot version. Signed-off-by: Eddie James --- include/efi_tcg2.h | 44 --- include/tpm-v2.h | 135 + lib/tpm-v2.c | 700 + 3 files changed, 835 insertions(+), 44 deletions(-) diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h index 874306dc11..23016773f4 100644 --- a/include/efi_tcg2.h +++ b/include/efi_tcg2.h @@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability { #define BOOT_SERVICE_CAPABILITY_MIN \ offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks) -#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03" -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2 - -/** - * struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information - * - * @algorithm_id: algorithm defined in enum tpm2_algorithms - * @digest_size: size of the algorithm - */ -struct tcg_efi_spec_id_event_algorithm_size { - u16 algorithm_id; - u16 digest_size; -} __packed; - -/** - * struct TCG_EfiSpecIDEventStruct - content of the event log header - * - * @signature: signature, set to Spec ID Event03 - * @platform_class:class defined in TCG ACPI Specification - * Client Common Header. - * @spec_version_minor:minor version - * @spec_version_major:major version - * @spec_version_errata: major version - * @uintn_size:size of the efi_uintn_t fields used in various - * data structures used in this specification. - * 0x01 indicates u32 and 0x02 indicates u64 - * @number_of_algorithms: hashing algorithms used in this event log - * @digest_sizes: array of number_of_algorithms pairs - * 1st member defines the algorithm id - * 2nd member defines the algorithm size - */ -struct tcg_efi_spec_id_event { - u8 signature[16]; - u32 platform_class; - u8 spec_version_minor; - u8 spec_version_major; - u8 spec_errata; - u8 uintn_size; - u32 number_of_algorithms; - struct tcg_efi_spec_id_event_algorithm_size digest_sizes[]; -} __packed; - /** * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log * @version: version number for this structure diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 85feda3e06..62a245e9d9 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -214,6 +214,50 @@ struct tcg_pcr_event2 { u8 event[]; } __packed; +/** + * struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information + * + * @algorithm_id: algorithm defined in enum tpm2_algorithms + * @digest_size: size of the algorithm + */ +struct tcg_efi_spec_id_event_algorithm_size { + u16 algorithm_id; + u16 digest_size; +} __packed; + +#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03" +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2 +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0 +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2 + +/** + * struct TCG_EfiSpecIDEventStruct - content of the event log header + * + * @signature: signature, set to Spec ID Event03 + * @platform_class:class defined in TCG ACPI Specification + * Client Common Header. + * @spec_version_minor:minor version + * @spec_version_major:major version + * @spec_version_errata: major version + * @uintn_size:size of the efi_uintn_t fields used in various + * data structures used in this specification. + * 0x01 indicates u32 and 0x02 indicates u64 + * @number_of_algorithms: hashing algorithms used in this event log + * @digest_sizes: array of number_of_algorithms pairs + * 1st member defines the algorithm id + * 2nd member defines the algorithm size + */ +struct tcg_efi_spec_id_event { + u8 signature[16]; + u32 platform_class; + u8 spec_version_minor; + u8 spec_version_major; + u8 spec_errata; + u8 uintn_size; + u32 number_of_algorithms; + struct tcg_efi_spec_id_event_algorithm_size digest_sizes[]; +} __packed; + /** * TPM2 Structure Tags for command/response buffers. * @@ -340,6 +384,24 @@ enum tpm2_algorithms { TPM2_ALG_SM3_256= 0x12, }; +static inline u16 tpm2_algorithm_to_len(enum tpm2_algorithms a) +{ + switch (a) { + case TPM2_ALG_SHA1: +
[PATCH 3/3] bootm: Support boot measurement
Add a configuration option to measure the boot through the bootm function. Signed-off-by: Eddie James --- boot/bootm.c| 53 + cmd/bootm.c | 2 ++ common/Kconfig | 6 ++ include/image.h | 1 + 4 files changed, 62 insertions(+) diff --git a/boot/bootm.c b/boot/bootm.c index a4c0870c0f..7f64d79035 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -22,6 +22,9 @@ #include #include #include +#if defined(CONFIG_MEASURED_BOOT) +#include +#endif #if defined(CONFIG_CMD_USB) #include #endif @@ -713,6 +716,56 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc, if (!ret && (states & BOOTM_STATE_FINDOTHER)) ret = bootm_find_other(cmdtp, flag, argc, argv); +#if defined(CONFIG_MEASURED_BOOT) + if (!ret && (states & BOOTM_STATE_MEASURE)) { + void *initrd_buf; + void *image_buf; + const char *s; + u32 rd_len; + + ret = tcg2_measurement_init(); + if (ret) + goto measure_err; + + image_buf = map_sysmem(images->os.image_start, + images->os.image_len); + ret = tcg2_measure_data(8, images->os.image_len, image_buf, + EV_COMPACT_HASH, strlen("linux") + 1, + (u8 *)"linux"); + if (ret) + goto unmap_image; + + rd_len = images->rd_end - images->rd_start; + initrd_buf = map_sysmem(images->rd_start, rd_len); + ret = tcg2_measure_data(8, rd_len, initrd_buf, EV_COMPACT_HASH, + strlen("initrd") + 1, (u8 *)"initrd"); + if (ret) + goto unmap_initrd; + + ret = tcg2_measure_data(9, images->ft_len, + (u8 *)images->ft_addr, + EV_TABLE_OF_DEVICES, strlen("dts") + 1, + (u8 *)"dts"); + if (ret) + goto unmap_initrd; + + s = env_get("bootargs"); + if (!s) + s = ""; + tcg2_measure_data(1, strlen(s) + 1, (u8 *)s, + EV_PLATFORM_CONFIG_FLAGS, strlen(s) + 1, + (u8 *)s); + +unmap_initrd: + unmap_sysmem(initrd_buf); +unmap_image: + unmap_sysmem(image_buf); + tcg2_measurement_term(); +measure_err: + ret = 0; + } +#endif + /* Load the OS */ if (!ret && (states & BOOTM_STATE_LOADOS)) { iflag = bootm_disable_interrupts(); diff --git a/cmd/bootm.c b/cmd/bootm.c index 37c2af96e0..0c4a713e02 100644 --- a/cmd/bootm.c +++ b/cmd/bootm.c @@ -161,6 +161,8 @@ int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) BOOTM_STATE_OS_GO; if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH)) states |= BOOTM_STATE_RAMDISK; + if (IS_ENABLED(CONFIG_MEASURED_BOOT)) + states |= BOOTM_STATE_MEASURE; if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS)) states |= BOOTM_STATE_OS_CMDLINE; ret = do_bootm_states(cmdtp, flag, argc, argv, states, , 1); diff --git a/common/Kconfig b/common/Kconfig index 21434c5cf1..57ef68e4f3 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -799,6 +799,12 @@ config AVB_BUF_SIZE endif # AVB_VERIFY +config MEASURED_BOOT + bool "Measure the boot to TPM and event log" + depends on HASH && TPM_V2 + help + This option enables measurement of the boot process. + config SCP03 bool "Build SCP03 - Secure Channel Protocol O3 - controls" depends on OPTEE || SANDBOX diff --git a/include/image.h b/include/image.h index 6f21dafba8..b00803eeac 100644 --- a/include/image.h +++ b/include/image.h @@ -406,6 +406,7 @@ struct bootm_headers { #define BOOTM_STATE_OS_FAKE_GO 0x0200 /* 'Almost' run the OS */ #define BOOTM_STATE_OS_GO 0x0400 #define BOOTM_STATE_PRE_LOAD 0x0800 +#define BOOTM_STATE_MEASURE0x1000 int state; #if defined(CONFIG_LMB) && !defined(USE_HOSTCC) -- 2.31.1
[PATCH 0/3] tpm: Support boot measurements
This series adds support for measuring the boot images more generically than the existing EFI support. The series includes optional measurement from the bootm command. Eventually the EFI code could be refactored to use the generic functions. Eddie James (3): tpm: Fix spelling for tpmu_ha union tpm: Support boot measurements bootm: Support boot measurement boot/bootm.c | 53 cmd/bootm.c| 2 + common/Kconfig | 6 + include/efi_tcg2.h | 44 --- include/image.h| 1 + include/tpm-v2.h | 139 - lib/tpm-v2.c | 700 + 7 files changed, 899 insertions(+), 46 deletions(-) -- 2.31.1
[PATCH 1/3] tpm: Fix spelling for tpmu_ha union
tmpu -> tpmu Signed-off-by: Eddie James --- include/tpm-v2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 737e57551d..85feda3e06 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -167,7 +167,7 @@ struct tcg_pcr_event { /** * Definition of TPMU_HA Union */ -union tmpu_ha { +union tpmu_ha { u8 sha1[TPM2_SHA1_DIGEST_SIZE]; u8 sha256[TPM2_SHA256_DIGEST_SIZE]; u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE]; @@ -183,7 +183,7 @@ union tmpu_ha { */ struct tpmt_ha { u16 hash_alg; - union tmpu_ha digest; + union tpmu_ha digest; } __packed; /** -- 2.31.1
[PATCH v4 2/6] tpm: Support boot measurements
Add TPM2 functions to support boot measurement. This includes starting up the TPM, initializing/appending the event log, and measuring the U-Boot version. Much of the code was used in the EFI subsystem, so remove it there and use the common functions. Signed-off-by: Eddie James --- include/efi_tcg2.h| 44 -- include/tpm-v2.h | 254 ++ lib/efi_loader/efi_tcg2.c | 975 +++--- lib/tpm-v2.c | 799 +++ 4 files changed, 1129 insertions(+), 943 deletions(-) diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h index 874306dc11..23016773f4 100644 --- a/include/efi_tcg2.h +++ b/include/efi_tcg2.h @@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability { #define BOOT_SERVICE_CAPABILITY_MIN \ offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks) -#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03" -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2 - -/** - * struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information - * - * @algorithm_id: algorithm defined in enum tpm2_algorithms - * @digest_size: size of the algorithm - */ -struct tcg_efi_spec_id_event_algorithm_size { - u16 algorithm_id; - u16 digest_size; -} __packed; - -/** - * struct TCG_EfiSpecIDEventStruct - content of the event log header - * - * @signature: signature, set to Spec ID Event03 - * @platform_class:class defined in TCG ACPI Specification - * Client Common Header. - * @spec_version_minor:minor version - * @spec_version_major:major version - * @spec_version_errata: major version - * @uintn_size:size of the efi_uintn_t fields used in various - * data structures used in this specification. - * 0x01 indicates u32 and 0x02 indicates u64 - * @number_of_algorithms: hashing algorithms used in this event log - * @digest_sizes: array of number_of_algorithms pairs - * 1st member defines the algorithm id - * 2nd member defines the algorithm size - */ -struct tcg_efi_spec_id_event { - u8 signature[16]; - u32 platform_class; - u8 spec_version_minor; - u8 spec_version_major; - u8 spec_errata; - u8 uintn_size; - u32 number_of_algorithms; - struct tcg_efi_spec_id_event_algorithm_size digest_sizes[]; -} __packed; - /** * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log * @version: version number for this structure diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 85feda3e06..7057f67176 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -214,6 +214,50 @@ struct tcg_pcr_event2 { u8 event[]; } __packed; +/** + * struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information + * + * @algorithm_id: algorithm defined in enum tpm2_algorithms + * @digest_size: size of the algorithm + */ +struct tcg_efi_spec_id_event_algorithm_size { + u16 algorithm_id; + u16 digest_size; +} __packed; + +#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03" +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2 +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0 +#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2 + +/** + * struct TCG_EfiSpecIDEventStruct - content of the event log header + * + * @signature: signature, set to Spec ID Event03 + * @platform_class:class defined in TCG ACPI Specification + * Client Common Header. + * @spec_version_minor:minor version + * @spec_version_major:major version + * @spec_version_errata: major version + * @uintn_size:size of the efi_uintn_t fields used in various + * data structures used in this specification. + * 0x01 indicates u32 and 0x02 indicates u64 + * @number_of_algorithms: hashing algorithms used in this event log + * @digest_sizes: array of number_of_algorithms pairs + * 1st member defines the algorithm id + * 2nd member defines the algorithm size + */ +struct tcg_efi_spec_id_event { + u8 signature[16]; + u32 platform_class; + u8 spec_version_minor; + u8 spec_version_major; + u8 spec_errata; + u8 uintn_size; + u32 number_of_algorithms; + struct tcg_efi_spec_id_event_algorithm_size digest_sizes[]; +} __packed; + /** * TPM2 Structure Tags for command/response buffers. * @@ -340,6 +384,26 @@
[PATCH v4 3/6] bootm: Support boot measurement
Add a configuration option to measure the boot through the bootm function. Add the measurement state to the booti and bootz paths as well. Signed-off-by: Eddie James --- boot/Kconfig| 23 boot/bootm.c| 70 + cmd/booti.c | 1 + cmd/bootm.c | 2 ++ cmd/bootz.c | 1 + include/bootm.h | 2 ++ include/image.h | 1 + 7 files changed, 100 insertions(+) diff --git a/boot/Kconfig b/boot/Kconfig index fdcfbae7b2..831b9e954c 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -601,6 +601,29 @@ config LEGACY_IMAGE_FORMAT loaded. If a board needs the legacy image format support in this case, enable it here. +config MEASURED_BOOT + bool "Measure boot images and configuration to TPM and event log" + depends on HASH && TPM_V2 + help + This option enables measurement of the boot process. Measurement + involves creating cryptographic hashes of the binary images that + are booting and storing them in the TPM. In addition, a log of + these hashes is stored in memory for the OS to verify the booted + images and configuration. Enable this if the OS has configured + some memory area for the event log and you intend to use some + attestation tools on your system. + +if MEASURED_BOOT + config MEASURE_DEVICETREE + bool "Measure the devicetree image" + default y if MEASURED_BOOT + help + On some platforms, the devicetree is not static as it may contain + random MAC addresses or other such data that changes each boot. + Therefore, it should not be measured into the TPM. In that case, + disable the measurement here. +endif # MEASURED_BOOT + config SUPPORT_RAW_INITRD bool "Enable raw initrd images" help diff --git a/boot/bootm.c b/boot/bootm.c index 15fce8ad95..c8423f2c60 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -22,6 +22,7 @@ #include #include #include +#include #if defined(CONFIG_CMD_USB) #include #endif @@ -659,6 +660,72 @@ int bootm_process_cmdline_env(int flags) return 0; } +int bootm_measure(struct bootm_headers *images) +{ + int ret = 0; + + /* Skip measurement if EFI is going to do it */ + if (images->os.os == IH_OS_EFI && + IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL) && + IS_ENABLED(CONFIG_BOOTM_EFI)) + return ret; + + if (IS_ENABLED(CONFIG_MEASURED_BOOT)) { + struct tcg2_event_log elog; + struct udevice *dev; + void *initrd_buf; + void *image_buf; + const char *s; + u32 rd_len; + + ret = tcg2_measurement_init(, ); + if (ret) + return ret; + + image_buf = map_sysmem(images->os.image_start, + images->os.image_len); + ret = tcg2_measure_data(dev, , 8, images->os.image_len, + image_buf, EV_COMPACT_HASH, + strlen("linux") + 1, (u8 *)"linux"); + if (ret) + goto unmap_image; + + rd_len = images->rd_end - images->rd_start; + initrd_buf = map_sysmem(images->rd_start, rd_len); + ret = tcg2_measure_data(dev, , 8, rd_len, initrd_buf, + EV_COMPACT_HASH, strlen("initrd") + 1, + (u8 *)"initrd"); + if (ret) + goto unmap_initrd; + + if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) { + ret = tcg2_measure_data(dev, , 9, images->ft_len, + (u8 *)images->ft_addr, + EV_TABLE_OF_DEVICES, + strlen("dts") + 1, + (u8 *)"dts"); + if (ret) + goto unmap_initrd; + } + + s = env_get("bootargs"); + if (!s) + s = ""; + ret = tcg2_measure_data(dev, , 1, strlen(s) + 1, (u8 *)s, + EV_PLATFORM_CONFIG_FLAGS, + strlen(s) + 1, (u8 *)s); + +unmap_initrd: + unmap_sysmem(initrd_buf); + +unmap_image: + unmap_sysmem(image_buf); + tcg2_measurement_term(dev, , ret != 0); + } + + return ret; +} + /** * Execute selected states of the bootm command. * @@ -710,6 +777,9 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc, if (!ret &&
[PATCH v4 5/6] test: Add sandbox TPM boot measurement
Use the sandbox TPM driver to measure some boot images in a unit test case. Signed-off-by: Eddie James --- arch/sandbox/dts/sandbox.dtsi | 14 arch/sandbox/dts/test.dts | 13 +++ configs/sandbox_defconfig | 1 + include/test/suites.h | 1 + test/boot/Makefile| 1 + test/boot/measurement.c | 66 +++ test/cmd_ut.c | 2 ++ 7 files changed, 98 insertions(+) create mode 100644 test/boot/measurement.c diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index 18bf1cb5b6..3f0e192a83 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -4,9 +4,22 @@ * and sandbox64 builds. */ +#include + #define USB_CLASS_HUB 9 / { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman { }; @@ -332,6 +345,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; triangle { diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 9d96e479ca..c334b89faa 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -9,6 +9,7 @@ /dts-v1/; +#include #include #include #include @@ -66,6 +67,17 @@ osd0 = "/osd"; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman: binman { }; @@ -1343,6 +1355,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; uart0: serial { diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 34c342b6f5..9c4985adcf 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -337,3 +337,4 @@ CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +CONFIG_MEASURED_BOOT=y diff --git a/include/test/suites.h b/include/test/suites.h index 9ce49cbb03..4c284bbeaa 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -44,6 +44,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); +int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/test/boot/Makefile b/test/boot/Makefile index 22ed61c8fa..2dbb032a7e 100644 --- a/test/boot/Makefile +++ b/test/boot/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o obj-$(CONFIG_FIT) += image.o +obj-$(CONFIG_MEASURED_BOOT) += measurement.o obj-$(CONFIG_EXPO) += expo.o diff --git a/test/boot/measurement.c b/test/boot/measurement.c new file mode 100644 index 00..2155208894 --- /dev/null +++ b/test/boot/measurement.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for measured boot functions + * + * Copyright 2023 IBM Corp. + * Written by Eddie James + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MEASUREMENT_TEST(_name, _flags)\ + UNIT_TEST(_name, _flags, measurement_test) + +static int measure(struct unit_test_state *uts) +{ + struct bootm_headers images; + const size_t size = 1024; + u8 *kernel; + u8 *initrd; + size_t i; + + kernel = malloc(size); + initrd = malloc(size); + + images.os.image_start = map_to_sysmem(kernel); + images.os.image_len = size; + + images.rd_start = map_to_sysmem(initrd); + images.rd_end = images.rd_start + size; + + images.ft_addr = malloc(size); + images.ft_len = size; + + env_set("bootargs", "measurement testing"); + + for (i = 0; i < size; ++i) { + kernel[i] = (u8)(0xf0 | (i & 0xf)); + initrd[i] = (u8)((i & 0xf0) | 0xf); + ((u8 *)images.ft_addr)[i] = (u8)(i & 0xff); + } + + ut_assertok(bootm_measure()); + + free(images.ft_addr); + free(ini
[PATCH v4 0/6] tpm: Support boot measurements
This series adds support for measuring the boot images more generically than the existing EFI support. Several EFI functions have been moved to the TPM layer. The series includes optional measurement from the bootm command. A new test case has been added for the bootm measurement to test the new path, and the sandbox TPM2 driver has been updated to support this use case. Changes since v3: - Reordered headers - Refactored more of EFI code into common code Removed digest_info structure and instead used the common alg_to_mask and alg_to_len Improved event log parsing in common code to get it equivalent to EFI Common code now extends PCR if previous bootloader stage couldn't No need to allocate memory in the common code, so EFI copies the discovered buffer like it did before Rename efi measure_event function Changes since v2: - Add documentation. - Changed reserved memory address to the top of the RAM for sandbox dts. - Add measure state to booti and bootz. - Skip measurement for EFI images that should be measured Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions. - Add test case - Drop #ifdefs for bootm - Add devicetree measurement config option - Update sandbox TPM driver Eddie James (6): tpm: Fix spelling for tpmu_ha union tpm: Support boot measurements bootm: Support boot measurement tpm: sandbox: Update for needed TPM2 capabilities test: Add sandbox TPM boot measurement doc: Add measured boot documentation arch/sandbox/dts/sandbox.dtsi | 14 + arch/sandbox/dts/test.dts | 13 + boot/Kconfig | 23 + boot/bootm.c | 70 +++ cmd/booti.c| 1 + cmd/bootm.c| 2 + cmd/bootz.c| 1 + configs/sandbox_defconfig | 1 + doc/usage/index.rst| 1 + doc/usage/measured_boot.rst| 23 + drivers/tpm/tpm2_tis_sandbox.c | 100 +++- include/bootm.h| 2 + include/efi_tcg2.h | 44 -- include/image.h| 1 + include/test/suites.h | 1 + include/tpm-v2.h | 258 - lib/efi_loader/efi_tcg2.c | 975 +++-- lib/tpm-v2.c | 799 +++ test/boot/Makefile | 1 + test/boot/measurement.c| 66 +++ test/cmd_ut.c | 2 + 21 files changed, 1425 insertions(+), 973 deletions(-) create mode 100644 doc/usage/measured_boot.rst create mode 100644 test/boot/measurement.c -- 2.31.1
[PATCH v4 6/6] doc: Add measured boot documentation
Briefly describe the feature and specify the requirements. Signed-off-by: Eddie James --- doc/usage/index.rst | 1 + doc/usage/measured_boot.rst | 23 +++ 2 files changed, 24 insertions(+) create mode 100644 doc/usage/measured_boot.rst diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 7d4a1cbc10..c3efdf61df 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -12,6 +12,7 @@ Use U-Boot partitions cmdline semihosting + measured_boot Shell commands -- diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst new file mode 100644 index 00..13fd42a2fb --- /dev/null +++ b/doc/usage/measured_boot.rst @@ -0,0 +1,23 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Measured Boot += + +U-Boot can perform a measured boot, the process of hashing various components +of the boot process, extending the results in the TPM and logging the +component's measurement in memory for the operating system to consume. + +Requirements +- + +A hardware TPM 2.0 supported by the U-Boot drivers +CONFIG_TPM=y +CONFIG_MEASURED_BOOT=y +Device-tree configuration of the TPM device to specify the memory area +for event logging. The TPM device node must either contain a phandle to +a reserved memory region or "linux,sml-base" and "linux,sml-size" +indicating the address and size of the memory region. An example can be +found in arch/sandbox/dts/test.dts +The operating system must also be configured to use the memory regions +specified in the U-Boot device-tree in order to make use of the event +log. -- 2.31.1
[PATCH v4 1/6] tpm: Fix spelling for tpmu_ha union
tmpu -> tpmu Signed-off-by: Eddie James Reviewed-by: Ilias Apalodimas --- include/tpm-v2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 737e57551d..85feda3e06 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -167,7 +167,7 @@ struct tcg_pcr_event { /** * Definition of TPMU_HA Union */ -union tmpu_ha { +union tpmu_ha { u8 sha1[TPM2_SHA1_DIGEST_SIZE]; u8 sha256[TPM2_SHA256_DIGEST_SIZE]; u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE]; @@ -183,7 +183,7 @@ union tmpu_ha { */ struct tpmt_ha { u16 hash_alg; - union tmpu_ha digest; + union tpmu_ha digest; } __packed; /** -- 2.31.1
[PATCH v4 4/6] tpm: sandbox: Update for needed TPM2 capabilities
The driver needs to support getting the PCRs in the capabilities command. Fix various other things and support the max number of PCRs for TPM2. Signed-off-by: Eddie James Reviewed-by: Simon Glass --- drivers/tpm/tpm2_tis_sandbox.c | 100 - 1 file changed, 72 insertions(+), 28 deletions(-) diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c index dd94bdc31f..ea7fb5e3cb 100644 --- a/drivers/tpm/tpm2_tis_sandbox.c +++ b/drivers/tpm/tpm2_tis_sandbox.c @@ -22,11 +22,6 @@ enum tpm2_hierarchy { TPM2_HIERARCHY_NB, }; -/* Subset of supported capabilities */ -enum tpm2_capability { - TPM_CAP_TPM_PROPERTIES = 0x6, -}; - /* Subset of supported properties */ #define TPM2_PROPERTIES_OFFSET 0x020E @@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property { TPM2_PROPERTY_NB, }; -#define SANDBOX_TPM_PCR_NB 1 +#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS +#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8) /* * Information about our TPM emulation. This is preserved in the sandbox @@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, int i, j; /* TPM2_GetProperty */ - u32 capability, property, property_count; + u32 capability, property, property_count, val; /* TPM2_PCR_Read/Extend variables */ int pcr_index = 0; @@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, case TPM2_CC_GET_CAPABILITY: capability = get_unaligned_be32(sent); sent += sizeof(capability); - if (capability != TPM_CAP_TPM_PROPERTIES) { - printf("Sandbox TPM only support TPM_CAPABILITIES\n"); - return TPM2_RC_HANDLE; - } - property = get_unaligned_be32(sent); sent += sizeof(property); - property -= TPM2_PROPERTIES_OFFSET; - property_count = get_unaligned_be32(sent); sent += sizeof(property_count); - if (!property_count || - property + property_count > TPM2_PROPERTY_NB) { + + switch (capability) { + case TPM2_CAP_PCRS: + break; + case TPM2_CAP_TPM_PROPERTIES: + if (!property_count) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + + if (property > TPM2_PROPERTIES_OFFSET && + ((property - TPM2_PROPERTIES_OFFSET) + +property_count > TPM2_PROPERTY_NB)) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + break; + default: + printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or " + "TPM2_CAP_TPM_PROPERTIES\n"); rc = TPM2_RC_HANDLE; return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); } @@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, put_unaligned_be32(capability, recv); recv += sizeof(capability); - /* Give the number of properties that follow */ - put_unaligned_be32(property_count, recv); - recv += sizeof(property_count); - - /* Fill with the properties */ - for (i = 0; i < property_count; i++) { - put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property + - i, recv); - recv += sizeof(property); - put_unaligned_be32(tpm->properties[property + i], - recv); - recv += sizeof(property); + switch (capability) { + case TPM2_CAP_PCRS: + /* Give the number of algorithms supported - just SHA256 */ + put_unaligned_be32(1, recv); + recv += sizeof(u32); + + /* Give SHA256 algorithm */ + put_unaligned_be16(TPM2_ALG_SHA256, recv); + recv += sizeof(u16); + + /* Select the PCRs supported */ + *recv = SANDBOX_TPM_PCR_SELECT_MAX; + recv++; + + /* Activate all the PCR bits */ + for (i = 0; i < SANDBOX_TPM_PCR_SELECT_
Re: [PATCH v4 3/6] bootm: Support boot measurement
On 1/25/23 19:41, Simon Glass wrote: Hi Eddie, On Wed, 25 Jan 2023 at 10:18, Eddie James wrote: Add a configuration option to measure the boot through the bootm function. Add the measurement state to the booti and bootz paths as well. Signed-off-by: Eddie James --- boot/Kconfig| 23 boot/bootm.c| 70 + cmd/booti.c | 1 + cmd/bootm.c | 2 ++ cmd/bootz.c | 1 + include/bootm.h | 2 ++ include/image.h | 1 + 7 files changed, 100 insertions(+) Can you please add a change log? I recall making comments but cannot see the changes here. Sorry, sure. I put them all in the cover letter, but I can add them here too. Thanks, Eddie Regards, Simon
Re: [PATCH v3 2/6] tpm: Support boot measurements
On 1/16/23 06:00, Ilias Apalodimas wrote: Hi Eddie +static inline u16 tpm2_algorithm_to_len(enum tpm2_algorithms a) +{ + switch (a) { + case TPM2_ALG_SHA1: + return TPM2_SHA1_DIGEST_SIZE; + case TPM2_ALG_SHA256: + return TPM2_SHA256_DIGEST_SIZE; + case TPM2_ALG_SHA384: + return TPM2_SHA384_DIGEST_SIZE; + case TPM2_ALG_SHA512: + return TPM2_SHA512_DIGEST_SIZE; + default: + return 0; + } +} Any reason we can't move the static 'const struct digest_info hash_algo_list' from the efi_tcg.c here? We can then move the functions defined in there alg_to_mask and alg_to_len. And since alg_to_mask is really just a bitshift maybe replace that? Hi, It seems more efficient to keep the switch statement rather than iterate through the structure array looking for the matching hash algorithm? I could remove the 'static const struct digest_info hash_algo_list' in efi_tcg2.c and instead use the tpm2_algorithm_to_len and tpm2_algorithm_to_mask in efi_tcg2.c. What do you think? + +#define tpm2_algorithm_to_mask(a) (1 << (a)) + /* NV index attributes */ enum tpm_index_attrs { TPMA_NV_PPWRITE = 1UL << 0, @@ -419,6 +481,142 @@ enum { HR_NV_INDEX = TPM_HT_NV_INDEX << HR_SHIFT, }; +/** + * struct tcg2_event_log - Container for managing the platform event log + * + * @log: Address of the log + * @log_position: Current entry position + * @log_size: Log space available + */ +struct tcg2_event_log { + u8 *log; + u32 log_position; - } - } - - *pcr_banks = pcrs.count; - - return 0; -out: - return -1; -} - /** * __get_active_pcr_banks() - returns the currently active PCR banks * @@ -638,7 +378,7 @@ static efi_status_t __get_active_pcr_banks(u32 *active_pcr_banks) efi_status_t ret; int err; - ret = platform_get_tpm2_device(); + ret = tcg2_platform_get_tpm2(); if (ret != EFI_SUCCESS) goto out; We can get rid of this entirely and just define the efi_tcg2_get_active_pcr_banks in the efi_tcg.c now. __get_active_pcr_banks == tcg2_get_active_pcr_banks with the only diffence being the udevice which is now an argument Ack. @@ -654,70 +394,6 @@ out: return ret; } * efi_tcg2_get_capability() - protocol capability information and state information * @@ -759,7 +435,7 @@ efi_tcg2_get_capability(struct efi_tcg2_protocol *this, capability->protocol_version.major = 1; capability->protocol_version.minor = 1; + +static int tcg2_log_append_check(struct tcg2_event_log *elog, u32 pcr_index, +u32 event_type, +struct tpml_digest_values *digest_list, +u32 size, const u8 *event) +{ + u32 event_size; + u8 *log; + + event_size = size + tcg2_event_get_size(digest_list); + if (elog->log_position + event_size > elog->log_size) { + printf("%s: log too large: %u + %u > %u\n", __func__, + elog->log_position, event_size, elog->log_size); + return -ENOBUFS; + } + + log = elog->log + elog->log_position; + elog->log_position += event_size; + + tcg2_log_append(pcr_index, event_type, digest_list, size, event, log); + + return 0; +} + +static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log *elog) +{ I think we need to re-use efi_init_event_log here. The reason is that on Arm devices TF-A is capable of constructing an eventlog and passing it along in memory. That code takes that into account and tries to reuse the existing EventLog passed from previous boot stages. The main difference between the EFI function and this one is the allocated memory of the EventLog itself. But even in this case, it would be better to tweak the EFI code and do create log -> Allocate EFI memory -> copy log and then use that for EFI OK... I'll try and get that to work. I see some potential issues like the fact that EFI finds the platform event log differently. + struct tcg_efi_spec_id_event *ev; + struct tcg_pcr_event *log; + u32 event_size; + u32 count = 0; + u32 log_size; + u32 active; + u32 mask; + size_t i; + u16 len; + int rc; + + rc = tcg2_get_active_pcr_banks(dev, ); + if (rc) + return rc; + + event_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes); + for (i = 0; i < ARRAY_SIZE(tcg2algos); ++i) { + mask = tpm2_algorithm_to_mask(tcg2algos[i]); + + if (!(active & mask)) + continue; + + switch (tcg2algos[i]) { + case TPM2_ALG_SHA1: + case TPM2_ALG_SHA256: + case TPM2_ALG_SHA384: + case
[PATCH v9 0/6] tpm: Support boot measurements
This series adds support for measuring the boot images more generically than the existing EFI support. Several EFI functions have been moved to the TPM layer. The series includes optional measurement from the bootm command. A new test case has been added for the bootm measurement to test the new path, and the sandbox TPM2 driver has been updated to support this use case. This series is based on Ilias' auto-startup series and Simon's additions. Changes since v8: - Fix a sandbox driver off-by-one error in checking the property type. - Fix log parsing again - any data corruption seen while replaying the event log was failing the entire measurement. - Added an option to ignore the existing log and a configuration option for systems to select that for the bootm measurement. This would only be selected for systems that know that U-Boot is the first stage bootloader. This is necessary because the reserved memory region may persist through resets and so U-Boot attempts to append to the previous boot's log. Changes since v7: - Change name of tcg2_init_log and add more documentation - Add a check, when parsing the event log header, to ensure that the previous stage bootloader used all the active PCRs. - Change name of tcg2_log_find_end - Fix the greater than or equal to check to exit the log parsing - Make sure log_position is 0 if there is any error discovering the log - Return errors parsing the log if the data is corrupt so that we don't end up with half a log Changes since v6: - Added comment for bootm_measure - Fixed line length in bootm_measure - Added Linaro copyright for all the EFI moved code - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to copy any discovered event log to the user's log if passed in. Changes since v5: - Re-ordered the patches to put the sandbox TPM driver patch second - Remove unused platform_get_eventlog in efi_tcg2.c - First look for tpm_event_log_* properties instead of linux,sml-* - Fix efi_tcg2.c compilation - Select SHA* configs - Remove the !SANDBOX dependency for EFI TCG2 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT is enabled Changes since v4: - Remove tcg2_measure_event function and check for NULL data in tcg2_measure_data - Use tpm_auto_startup - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function - Change PCR indexes for initrd and dtb - Drop u8 casting in measurement test - Use bullets in documentation Changes since v3: - Reordered headers - Refactored more of EFI code into common code Removed digest_info structure and instead used the common alg_to_mask and alg_to_len Improved event log parsing in common code to get it equivalent to EFI Common code now extends PCR if previous bootloader stage couldn't No need to allocate memory in the common code, so EFI copies the discovered buffer like it did before Rename efi measure_event function Changes since v2: - Add documentation. - Changed reserved memory address to the top of the RAM for sandbox dts. - Add measure state to booti and bootz. - Skip measurement for EFI images that should be measured Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions. - Add test case - Drop #ifdefs for bootm - Add devicetree measurement config option - Update sandbox TPM driver Eddie James (6): tpm: Fix spelling for tpmu_ha union tpm: sandbox: Update for needed TPM2 capabilities tpm: Support boot measurements bootm: Support boot measurement test: Add sandbox TPM boot measurement doc: Add measured boot documentation arch/sandbox/dts/sandbox.dtsi | 13 + arch/sandbox/dts/test.dts | 13 + boot/Kconfig | 32 + boot/bootm.c | 74 +++ cmd/booti.c|1 + cmd/bootm.c|2 + cmd/bootz.c|1 + configs/sandbox_defconfig |1 + doc/usage/index.rst|1 + doc/usage/measured_boot.rst| 23 + drivers/tpm/tpm2_tis_sandbox.c | 100 ++- include/bootm.h| 11 + include/efi_tcg2.h | 44 -- include/image.h|1 + include/test/suites.h |1 + include/tpm-v2.h | 263 +++- lib/Kconfig|4 + lib/efi_loader/Kconfig |2 - lib/efi_loader/efi_tcg2.c | 1054 +++- lib/tpm-v2.c | 814 test/boot/Makefile |1 + test/boot/measurement.c| 66 ++ test/cmd_ut.c |4 + 23 files changed, 1473 insertions(+), 1053 deletions(-) create mode 100644 doc/usage/measured_boot.rst create mode 100644 test/boot/measurement.c -- 2.31.1
[PATCH v9 5/6] test: Add sandbox TPM boot measurement
Use the sandbox TPM driver to measure some boot images in a unit test case. Signed-off-by: Eddie James Reviewed-by: Simon Glass Acked-by: Ilias Apalodimas --- Changes since v5: - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT is enabled. arch/sandbox/dts/sandbox.dtsi | 13 +++ arch/sandbox/dts/test.dts | 13 +++ configs/sandbox_defconfig | 1 + include/test/suites.h | 1 + test/boot/Makefile| 1 + test/boot/measurement.c | 66 +++ test/cmd_ut.c | 4 +++ 7 files changed, 99 insertions(+) create mode 100644 test/boot/measurement.c diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index 7e7fcff6d2..3442be7634 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -4,11 +4,23 @@ * and sandbox64 builds. */ +#include #include #define USB_CLASS_HUB 9 / { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman { }; @@ -336,6 +348,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; triangle { diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 9717103f10..7659effa71 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -9,6 +9,7 @@ /dts-v1/; +#include #include #include #include @@ -66,6 +67,17 @@ osd0 = "/osd"; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman: binman { }; @@ -1365,6 +1377,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; tpm { diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 77ade1f1d8..43b15b8446 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -335,3 +335,4 @@ CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +CONFIG_MEASURED_BOOT=y diff --git a/include/test/suites.h b/include/test/suites.h index 7c4960c004..b552fea9a9 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -44,6 +44,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); +int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/test/boot/Makefile b/test/boot/Makefile index 22ed61c8fa..2dbb032a7e 100644 --- a/test/boot/Makefile +++ b/test/boot/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o obj-$(CONFIG_FIT) += image.o +obj-$(CONFIG_MEASURED_BOOT) += measurement.o obj-$(CONFIG_EXPO) += expo.o diff --git a/test/boot/measurement.c b/test/boot/measurement.c new file mode 100644 index 00..9db2ed324c --- /dev/null +++ b/test/boot/measurement.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for measured boot functions + * + * Copyright 2023 IBM Corp. + * Written by Eddie James + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MEASUREMENT_TEST(_name, _flags)\ + UNIT_TEST(_name, _flags, measurement_test) + +static int measure(struct unit_test_state *uts) +{ + struct bootm_headers images; + const size_t size = 1024; + u8 *kernel; + u8 *initrd; + size_t i; + + kernel = malloc(size); + initrd = malloc(size); + + images.os.image_start = map_to_sysmem(kernel); + images.os.image_len = size; + + images.rd_start = map_to_sysmem(initrd); + images.rd_end = images.rd_start + size; + + images.ft_addr = malloc(size); + images.ft_len = size; + + env_set("bootargs", "measurement testing"); + + for (i = 0; i < size; ++i) { + kernel[i] = 0xf0 | (i & 0xf); + initrd[i] = (i & 0xf0) | 0xf; +
[PATCH v9 1/6] tpm: Fix spelling for tpmu_ha union
tmpu -> tpmu Signed-off-by: Eddie James Reviewed-by: Ilias Apalodimas --- include/tpm-v2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 2b6980e441..6684033deb 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -169,7 +169,7 @@ struct tcg_pcr_event { /** * Definition of TPMU_HA Union */ -union tmpu_ha { +union tpmu_ha { u8 sha1[TPM2_SHA1_DIGEST_SIZE]; u8 sha256[TPM2_SHA256_DIGEST_SIZE]; u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE]; @@ -185,7 +185,7 @@ union tmpu_ha { */ struct tpmt_ha { u16 hash_alg; - union tmpu_ha digest; + union tpmu_ha digest; } __packed; /** -- 2.31.1
Re: [PATCH v8 0/6] tpm: Support boot measurements
On 3/6/23 00:58, Ilias Apalodimas wrote: Hi Eddie, This has a few failures on the CI [0]. Please have a look and let me know if you can't understand the failures Hi, I think I have fixed the sandbox ones for v9. I'm unsure about the EFI selftest one in qemu targets... Thanks, Eddie [0] https://source.denx.de/u-boot/custodians/u-boot-tpm/-/pipelines/15471 Regards /Ilias On Fri, Mar 03, 2023 at 01:25:00PM -0600, Eddie James wrote: This series adds support for measuring the boot images more generically than the existing EFI support. Several EFI functions have been moved to the TPM layer. The series includes optional measurement from the bootm command. A new test case has been added for the bootm measurement to test the new path, and the sandbox TPM2 driver has been updated to support this use case. This series is based on Ilias' auto-startup series and Simon's additions. Changes since v7: - Change name of tcg2_init_log and add more documentation - Add a check, when parsing the event log header, to ensure that the previous stage bootloader used all the active PCRs. - Change name of tcg2_log_find_end - Fix the greater than or equal to check to exit the log parsing - Make sure log_position is 0 if there is any error discovering the log - Return errors parsing the log if the data is corrupt so that we don't end up with half a log Changes since v6: - Added comment for bootm_measure - Fixed line length in bootm_measure - Added Linaro copyright for all the EFI moved code - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to copy any discovered event log to the user's log if passed in. Changes since v5: - Re-ordered the patches to put the sandbox TPM driver patch second - Remove unused platform_get_eventlog in efi_tcg2.c - First look for tpm_event_log_* properties instead of linux,sml-* - Fix efi_tcg2.c compilation - Select SHA* configs - Remove the !SANDBOX dependency for EFI TCG2 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT is enabled Changes since v4: - Remove tcg2_measure_event function and check for NULL data in tcg2_measure_data - Use tpm_auto_startup - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function - Change PCR indexes for initrd and dtb - Drop u8 casting in measurement test - Use bullets in documentation Changes since v3: - Reordered headers - Refactored more of EFI code into common code Removed digest_info structure and instead used the common alg_to_mask and alg_to_len Improved event log parsing in common code to get it equivalent to EFI Common code now extends PCR if previous bootloader stage couldn't No need to allocate memory in the common code, so EFI copies the discovered buffer like it did before Rename efi measure_event function Changes since v2: - Add documentation. - Changed reserved memory address to the top of the RAM for sandbox dts. - Add measure state to booti and bootz. - Skip measurement for EFI images that should be measured Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions. - Add test case - Drop #ifdefs for bootm - Add devicetree measurement config option - Update sandbox TPM driver Eddie James (6): tpm: Fix spelling for tpmu_ha union tpm: sandbox: Update for needed TPM2 capabilities tpm: Support boot measurements bootm: Support boot measurement test: Add sandbox TPM boot measurement doc: Add measured boot documentation arch/sandbox/dts/sandbox.dtsi | 13 + arch/sandbox/dts/test.dts | 13 + boot/Kconfig | 23 + boot/bootm.c | 72 +++ cmd/booti.c|1 + cmd/bootm.c|2 + cmd/bootz.c|1 + configs/sandbox_defconfig |1 + doc/usage/index.rst|1 + doc/usage/measured_boot.rst| 23 + drivers/tpm/tpm2_tis_sandbox.c | 100 ++- include/bootm.h| 11 + include/efi_tcg2.h | 44 -- include/image.h|1 + include/test/suites.h |1 + include/tpm-v2.h | 255 +++- lib/Kconfig|4 + lib/efi_loader/Kconfig |2 - lib/efi_loader/efi_tcg2.c | 1054 +++- lib/tpm-v2.c | 815 test/boot/Makefile |1 + test/boot/measurement.c| 66 ++ test/cmd_ut.c |4 + 23 files changed, 1455 insertions(+), 1053 deletions(-) create mode 100644 doc/usage/measured_boot.rst create mode 100644 test/boot/measurement.c -- 2.31.1
[PATCH v9 2/6] tpm: sandbox: Update for needed TPM2 capabilities
The driver needs to support getting the PCRs in the capabilities command. Fix various other things and support the max number of PCRs for TPM2. Remove the !SANDBOX dependency for EFI TCG2 as well. Signed-off-by: Eddie James Reviewed-by: Simon Glass Acked-by: Ilias Apalodimas --- Changes since v8: - Use >= for checking the property against TPM2_PROPERTIES_OFFSET Changes since v5: - Remove the !SANDBOX dependency for EFI TCG2 drivers/tpm/tpm2_tis_sandbox.c | 100 - lib/efi_loader/Kconfig | 2 - 2 files changed, 72 insertions(+), 30 deletions(-) diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c index e4004cfcca..d15a28d9fc 100644 --- a/drivers/tpm/tpm2_tis_sandbox.c +++ b/drivers/tpm/tpm2_tis_sandbox.c @@ -22,11 +22,6 @@ enum tpm2_hierarchy { TPM2_HIERARCHY_NB, }; -/* Subset of supported capabilities */ -enum tpm2_capability { - TPM_CAP_TPM_PROPERTIES = 0x6, -}; - /* Subset of supported properties */ #define TPM2_PROPERTIES_OFFSET 0x020E @@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property { TPM2_PROPERTY_NB, }; -#define SANDBOX_TPM_PCR_NB 1 +#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS +#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8) /* * Information about our TPM emulation. This is preserved in the sandbox @@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, int i, j; /* TPM2_GetProperty */ - u32 capability, property, property_count; + u32 capability, property, property_count, val; /* TPM2_PCR_Read/Extend variables */ int pcr_index = 0; @@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, case TPM2_CC_GET_CAPABILITY: capability = get_unaligned_be32(sent); sent += sizeof(capability); - if (capability != TPM_CAP_TPM_PROPERTIES) { - printf("Sandbox TPM only support TPM_CAPABILITIES\n"); - return TPM2_RC_HANDLE; - } - property = get_unaligned_be32(sent); sent += sizeof(property); - property -= TPM2_PROPERTIES_OFFSET; - property_count = get_unaligned_be32(sent); sent += sizeof(property_count); - if (!property_count || - property + property_count > TPM2_PROPERTY_NB) { + + switch (capability) { + case TPM2_CAP_PCRS: + break; + case TPM2_CAP_TPM_PROPERTIES: + if (!property_count) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + + if (property >= TPM2_PROPERTIES_OFFSET && + ((property - TPM2_PROPERTIES_OFFSET) + +property_count > TPM2_PROPERTY_NB)) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + break; + default: + printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or " + "TPM2_CAP_TPM_PROPERTIES\n"); rc = TPM2_RC_HANDLE; return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); } @@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, put_unaligned_be32(capability, recv); recv += sizeof(capability); - /* Give the number of properties that follow */ - put_unaligned_be32(property_count, recv); - recv += sizeof(property_count); - - /* Fill with the properties */ - for (i = 0; i < property_count; i++) { - put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property + - i, recv); - recv += sizeof(property); - put_unaligned_be32(tpm->properties[property + i], - recv); - recv += sizeof(property); + switch (capability) { + case TPM2_CAP_PCRS: + /* Give the number of algorithms supported - just SHA256 */ + put_unaligned_be32(1, recv); + recv += sizeof(u32); + + /* Give SHA256 algorithm */ + put_unaligned_be16(TPM2_ALG_SHA256, recv); + recv += sizeof(u16); + + /* Se
[PATCH v9 4/6] bootm: Support boot measurement
Add a configuration option to measure the boot through the bootm function. Add the measurement state to the booti and bootz paths as well. Signed-off-by: Eddie James Reviewed-by: Simon Glass --- Changes since v8: - Added a configuration option to select to ignore any existing event log. This would only be selected for systems that know that U-Boot is the first stage bootloader. This is necessary because the reserved memory region may persist through resets and so U-Boot attempts to append to the previous boot's log. Changes since v6: - Added comment for bootm_measure - Fixed line length in bootm_measure boot/Kconfig| 32 + boot/bootm.c| 74 + cmd/booti.c | 1 + cmd/bootm.c | 2 ++ cmd/bootz.c | 1 + include/bootm.h | 11 include/image.h | 1 + 7 files changed, 122 insertions(+) diff --git a/boot/Kconfig b/boot/Kconfig index 5f491625c8..8119519c9f 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -629,6 +629,38 @@ config LEGACY_IMAGE_FORMAT loaded. If a board needs the legacy image format support in this case, enable it here. +config MEASURED_BOOT + bool "Measure boot images and configuration to TPM and event log" + depends on HASH && TPM_V2 + help + This option enables measurement of the boot process. Measurement + involves creating cryptographic hashes of the binary images that + are booting and storing them in the TPM. In addition, a log of + these hashes is stored in memory for the OS to verify the booted + images and configuration. Enable this if the OS has configured + some memory area for the event log and you intend to use some + attestation tools on your system. + +if MEASURED_BOOT + config MEASURE_DEVICETREE + bool "Measure the devicetree image" + default y if MEASURED_BOOT + help + On some platforms, the devicetree is not static as it may contain + random MAC addresses or other such data that changes each boot. + Therefore, it should not be measured into the TPM. In that case, + disable the measurement here. + + config MEASURE_IGNORE_LOG + bool "Ignore the existing event log" + default n + help + On platforms that use an event log memory region that persists + through system resets and are the first stage bootloader, then + this option should be enabled to ignore any existing data in the + event log memory region. +endif # MEASURED_BOOT + config SUPPORT_RAW_INITRD bool "Enable raw initrd images" help diff --git a/boot/bootm.c b/boot/bootm.c index 2eec60ec7b..2685bdbd74 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -22,6 +22,7 @@ #include #include #include +#include #if defined(CONFIG_CMD_USB) #include #endif @@ -659,6 +660,75 @@ int bootm_process_cmdline_env(int flags) return 0; } +int bootm_measure(struct bootm_headers *images) +{ + int ret = 0; + + /* Skip measurement if EFI is going to do it */ + if (images->os.os == IH_OS_EFI && + IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL) && + IS_ENABLED(CONFIG_BOOTM_EFI)) + return ret; + + if (IS_ENABLED(CONFIG_MEASURED_BOOT)) { + struct tcg2_event_log elog; + struct udevice *dev; + void *initrd_buf; + void *image_buf; + const char *s; + u32 rd_len; + bool ign; + + elog.log_size = 0; + ign = IS_ENABLED(CONFIG_MEASURE_IGNORE_LOG); + ret = tcg2_measurement_init(, , ign); + if (ret) + return ret; + + image_buf = map_sysmem(images->os.image_start, + images->os.image_len); + ret = tcg2_measure_data(dev, , 8, images->os.image_len, + image_buf, EV_COMPACT_HASH, + strlen("linux") + 1, (u8 *)"linux"); + if (ret) + goto unmap_image; + + rd_len = images->rd_end - images->rd_start; + initrd_buf = map_sysmem(images->rd_start, rd_len); + ret = tcg2_measure_data(dev, , 9, rd_len, initrd_buf, + EV_COMPACT_HASH, strlen("initrd") + 1, + (u8 *)"initrd"); + if (ret) + goto unmap_initrd; + + if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) { + ret = tcg2_measure_data(dev, , 0, images->ft_len, + (u8 *)images->ft_addr, +
[PATCH v9 6/6] doc: Add measured boot documentation
Briefly describe the feature and specify the requirements. Signed-off-by: Eddie James Reviewed-by: Simon Glass --- doc/usage/index.rst | 1 + doc/usage/measured_boot.rst | 23 +++ 2 files changed, 24 insertions(+) create mode 100644 doc/usage/measured_boot.rst diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 840c20c934..1cb6988d8a 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -12,6 +12,7 @@ Use U-Boot partitions cmdline semihosting + measured_boot Shell commands -- diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst new file mode 100644 index 00..8357b1f480 --- /dev/null +++ b/doc/usage/measured_boot.rst @@ -0,0 +1,23 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Measured Boot += + +U-Boot can perform a measured boot, the process of hashing various components +of the boot process, extending the results in the TPM and logging the +component's measurement in memory for the operating system to consume. + +Requirements +- + +* A hardware TPM 2.0 supported by the U-Boot drivers +* CONFIG_TPM=y +* CONFIG_MEASURED_BOOT=y +* Device-tree configuration of the TPM device to specify the memory area + for event logging. The TPM device node must either contain a phandle to + a reserved memory region or "linux,sml-base" and "linux,sml-size" + indicating the address and size of the memory region. An example can be + found in arch/sandbox/dts/test.dts +* The operating system must also be configured to use the memory regions + specified in the U-Boot device-tree in order to make use of the event + log. -- 2.31.1
[PATCH v9 3/6] tpm: Support boot measurements
Add TPM2 functions to support boot measurement. This includes starting up the TPM, initializing/appending the event log, and measuring the U-Boot version. Much of the code was used in the EFI subsystem, so remove it there and use the common functions. Signed-off-by: Eddie James --- Changes since v8: - Fix log parsing again - any data corruption seen while replaying the event log was failing the entire measurement. - Added an option to ignore the existing log. This should only be used for systems that know that U-Boot is the first stage bootloader. This is necessary because the reserved memory region may persist through resets and so U-Boot attempts to append to the previous boot's log. Changes since v7: - Change name of tcg2_init_log and add more documentation - Add a check, when parsing the event log header, to ensure that the previous stage bootloader used all the active PCRs. - Change name of tcg2_log_find_end - Fix the greater than or equal to check to exit the log parsing - Make sure log_position is 0 if there is any error discovering the log - Return errors parsing the log if the data is corrupt so that we don't end up with half a log Changes since v6: - Added Linaro copyright for all the EFI moved code - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to copy any discovered event log to the user's log if passed in. Changes since v5: - Remove unused platform_get_eventlog in efi_tcg2.c - First look for tpm_event_log_* properties instead of linux,sml-* - Fix efi_tcg2.c compilation - Select SHA* configs Changes since v4: - Remove tcg2_measure_event function and check for NULL data in tcg2_measure_data - Use tpm_auto_startup - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function Changes since v3: - Reordered headers - Refactored more of EFI code into common code Removed digest_info structure and instead used the common alg_to_mask and alg_to_len Improved event log parsing in common code to get it equivalent to EFI Common code now extends PCR if previous bootloader stage couldn't No need to allocate memory in the common code, so EFI copies the discovered buffer like it did before Rename efi measure_event function Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions include/efi_tcg2.h| 44 -- include/tpm-v2.h | 259 + lib/Kconfig |4 + lib/efi_loader/efi_tcg2.c | 1054 +++-- lib/tpm-v2.c | 814 5 files changed, 1154 insertions(+), 1021 deletions(-) diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h index b1c3abd097..b21c5cb3dd 100644 --- a/include/efi_tcg2.h +++ b/include/efi_tcg2.h @@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability { #define BOOT_SERVICE_CAPABILITY_MIN \ offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks) -#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03" -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0 -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2 - -/** - * struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information - * - * @algorithm_id: algorithm defined in enum tpm2_algorithms - * @digest_size: size of the algorithm - */ -struct tcg_efi_spec_id_event_algorithm_size { - u16 algorithm_id; - u16 digest_size; -} __packed; - -/** - * struct TCG_EfiSpecIDEventStruct - content of the event log header - * - * @signature: signature, set to Spec ID Event03 - * @platform_class:class defined in TCG ACPI Specification - * Client Common Header. - * @spec_version_minor:minor version - * @spec_version_major:major version - * @spec_version_errata: major version - * @uintn_size:size of the efi_uintn_t fields used in various - * data structures used in this specification. - * 0x01 indicates u32 and 0x02 indicates u64 - * @number_of_algorithms: hashing algorithms used in this event log - * @digest_sizes: array of number_of_algorithms pairs - * 1st member defines the algorithm id - * 2nd member defines the algorithm size - */ -struct tcg_efi_spec_id_event { - u8 signature[16]; - u32 platform_class; - u8 spec_version_minor; - u8 spec_version_major; - u8 spec_errata; - u8 uintn_size; - u32 number_of_algorithms; - struct tcg_efi_spec_id_event_algorithm_size digest_sizes[]; -} __packed; - /** * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log * @version: version number for this structure
Re: [PATCH v5 0/6] tpm: Support boot measurements
On 2/22/23 05:33, Ilias Apalodimas wrote: Hi Eddie, On Tue, Feb 21, 2023 at 04:38:58PM -0600, Eddie James wrote: On 2/6/23 06:20, Ilias Apalodimas wrote: Thanks Eddie, I quickly tested this but the EFI subsystem fails to initialize the TCG protocol properly now. Unfortunately I am on a business trip and I won't be able to take a look into why till next week Hi Ilias, I haven't had the opportunity to test this, have you? Thanks, Eddie Cheers /Ilias Still going through the code so bear with me. It seems that the EFI failure is coming from tcg2_platform_get_log() specifically if none of linux,sml-base nor tpm_event_log_addr if present in the dtb. One thing we should change here is look for tpm_event_log_addr first. The reason is that this is a very 'special' case in which TF-A fills in an eventlog for us, while linux,sml-base is more generic so I'd rather explicitly prefer TF-A id it prepared an eventlog for us. OK, thanks, this is helpful, I'll have a look. On the failure now, if none of the nodes is present we are looking for 'memory-region' within the TPM node? Looking at the DT specs the tpm should only support "compatible, label, linux,sml-base/size' am I missing something? I just had a commit merged for the reserved memory region: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/drivers/char/tpm/eventlog/of.c?id=1e2714bb83fc783d58701967391bea242c65eaff It isn't documented anywhere so far... Thanks, Eddie I also had to apply [0] for this to compile. You can 'easily' test the EFI changes by doing a 'printenv -e'. This will at least initialize the efi subsystem and install the needed EFI tables (you need CMD_NVEDIT_EFI=y) [0] https://source.denx.de/u-boot/custodians/u-boot-tpm/-/commit/d473596cd6900117485014476c70c49f202bd8da Hope this helps a bit. Let me know if I can help in any other way. Don't bother *testing* the eventlog for EFI on a full linux boot. I'll run that on v6 /Ilias On Thu, Feb 02, 2023 at 11:05:25AM -0600, Eddie James wrote: This series adds support for measuring the boot images more generically than the existing EFI support. Several EFI functions have been moved to the TPM layer. The series includes optional measurement from the bootm command. A new test case has been added for the bootm measurement to test the new path, and the sandbox TPM2 driver has been updated to support this use case. This series is based on Ilias' auto-startup series: https://lore.kernel.org/u-boot/20230126081844.591148-1-ilias.apalodi...@linaro.org/ Changes since v4: - Remove tcg2_measure_event function and check for NULL data in tcg2_measure_data - Use tpm_auto_startup - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function - Change PCR indexes for initrd and dtb - Drop u8 casting in measurement test - Use bullets in documentation Changes since v3: - Reordered headers - Refactored more of EFI code into common code Removed digest_info structure and instead used the common alg_to_mask and alg_to_len Improved event log parsing in common code to get it equivalent to EFI Common code now extends PCR if previous bootloader stage couldn't No need to allocate memory in the common code, so EFI copies the discovered buffer like it did before Rename efi measure_event function Changes since v2: - Add documentation. - Changed reserved memory address to the top of the RAM for sandbox dts. - Add measure state to booti and bootz. - Skip measurement for EFI images that should be measured Changes since v1: - Refactor TPM layer functions to allow EFI system to use them, and remove duplicate EFI functions. - Add test case - Drop #ifdefs for bootm - Add devicetree measurement config option - Update sandbox TPM driver Eddie James (6): tpm: Fix spelling for tpmu_ha union tpm: Support boot measurements bootm: Support boot measurement tpm: sandbox: Update for needed TPM2 capabilities test: Add sandbox TPM boot measurement doc: Add measured boot documentation arch/sandbox/dts/sandbox.dtsi | 14 + arch/sandbox/dts/test.dts | 13 + boot/Kconfig | 23 + boot/bootm.c | 70 +++ cmd/booti.c|1 + cmd/bootm.c|2 + cmd/bootz.c|1 + configs/sandbox_defconfig |1 + doc/usage/index.rst|1 + doc/usage/measured_boot.rst| 23 + drivers/tpm/tpm2_tis_sandbox.c | 100 +++- include/bootm.h|2 + include/efi_tcg2.h | 44 -- include/image.h|1 + include/test/suites.h |1 + include/tpm-v2.h | 246 +++- lib/efi_loader/efi_tcg2.c | 1010 +++- lib/tpm-v2.c | 771 test/boot/Mak
[PATCH v8 5/6] test: Add sandbox TPM boot measurement
Use the sandbox TPM driver to measure some boot images in a unit test case. Signed-off-by: Eddie James Reviewed-by: Simon Glass Acked-by: Ilias Apalodimas --- Changes since v5: - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT is enabled arch/sandbox/dts/sandbox.dtsi | 13 +++ arch/sandbox/dts/test.dts | 13 +++ configs/sandbox_defconfig | 1 + include/test/suites.h | 1 + test/boot/Makefile| 1 + test/boot/measurement.c | 66 +++ test/cmd_ut.c | 4 +++ 7 files changed, 99 insertions(+) create mode 100644 test/boot/measurement.c diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index 7e7fcff6d2..3442be7634 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -4,11 +4,23 @@ * and sandbox64 builds. */ +#include #include #define USB_CLASS_HUB 9 / { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman { }; @@ -336,6 +348,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; triangle { diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 9717103f10..7659effa71 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -9,6 +9,7 @@ /dts-v1/; +#include #include #include #include @@ -66,6 +67,17 @@ osd0 = "/osd"; }; + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + event_log: tcg_event_log { + no-map; + reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>; + }; + }; + binman: binman { }; @@ -1365,6 +1377,7 @@ tpm2 { compatible = "sandbox,tpm2"; + memory-region = <_log>; }; tpm { diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 77ade1f1d8..43b15b8446 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -335,3 +335,4 @@ CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +CONFIG_MEASURED_BOOT=y diff --git a/include/test/suites.h b/include/test/suites.h index 7c4960c004..b552fea9a9 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -44,6 +44,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); +int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/test/boot/Makefile b/test/boot/Makefile index 22ed61c8fa..2dbb032a7e 100644 --- a/test/boot/Makefile +++ b/test/boot/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o obj-$(CONFIG_FIT) += image.o +obj-$(CONFIG_MEASURED_BOOT) += measurement.o obj-$(CONFIG_EXPO) += expo.o diff --git a/test/boot/measurement.c b/test/boot/measurement.c new file mode 100644 index 00..9db2ed324c --- /dev/null +++ b/test/boot/measurement.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for measured boot functions + * + * Copyright 2023 IBM Corp. + * Written by Eddie James + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MEASUREMENT_TEST(_name, _flags)\ + UNIT_TEST(_name, _flags, measurement_test) + +static int measure(struct unit_test_state *uts) +{ + struct bootm_headers images; + const size_t size = 1024; + u8 *kernel; + u8 *initrd; + size_t i; + + kernel = malloc(size); + initrd = malloc(size); + + images.os.image_start = map_to_sysmem(kernel); + images.os.image_len = size; + + images.rd_start = map_to_sysmem(initrd); + images.rd_end = images.rd_start + size; + + images.ft_addr = malloc(size); + images.ft_len = size; + + env_set("bootargs", "measurement testing"); + + for (i = 0; i < size; ++i) { + kernel[i] = 0xf0 | (i & 0xf); + initrd[i] = (i & 0xf0) | 0xf; +
[PATCH v8 2/6] tpm: sandbox: Update for needed TPM2 capabilities
The driver needs to support getting the PCRs in the capabilities command. Fix various other things and support the max number of PCRs for TPM2. Remove the !SANDBOX dependency for EFI TCG2 as well. Signed-off-by: Eddie James Reviewed-by: Simon Glass Acked-by: Ilias Apalodimas --- Changes since v5: - Remove the !SANDBOX dependency for EFI TCG2 drivers/tpm/tpm2_tis_sandbox.c | 100 - lib/efi_loader/Kconfig | 2 - 2 files changed, 72 insertions(+), 30 deletions(-) diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c index e4004cfcca..f63c72814f 100644 --- a/drivers/tpm/tpm2_tis_sandbox.c +++ b/drivers/tpm/tpm2_tis_sandbox.c @@ -22,11 +22,6 @@ enum tpm2_hierarchy { TPM2_HIERARCHY_NB, }; -/* Subset of supported capabilities */ -enum tpm2_capability { - TPM_CAP_TPM_PROPERTIES = 0x6, -}; - /* Subset of supported properties */ #define TPM2_PROPERTIES_OFFSET 0x020E @@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property { TPM2_PROPERTY_NB, }; -#define SANDBOX_TPM_PCR_NB 1 +#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS +#define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8) /* * Information about our TPM emulation. This is preserved in the sandbox @@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, int i, j; /* TPM2_GetProperty */ - u32 capability, property, property_count; + u32 capability, property, property_count, val; /* TPM2_PCR_Read/Extend variables */ int pcr_index = 0; @@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, case TPM2_CC_GET_CAPABILITY: capability = get_unaligned_be32(sent); sent += sizeof(capability); - if (capability != TPM_CAP_TPM_PROPERTIES) { - printf("Sandbox TPM only support TPM_CAPABILITIES\n"); - return TPM2_RC_HANDLE; - } - property = get_unaligned_be32(sent); sent += sizeof(property); - property -= TPM2_PROPERTIES_OFFSET; - property_count = get_unaligned_be32(sent); sent += sizeof(property_count); - if (!property_count || - property + property_count > TPM2_PROPERTY_NB) { + + switch (capability) { + case TPM2_CAP_PCRS: + break; + case TPM2_CAP_TPM_PROPERTIES: + if (!property_count) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + + if (property > TPM2_PROPERTIES_OFFSET && + ((property - TPM2_PROPERTIES_OFFSET) + +property_count > TPM2_PROPERTY_NB)) { + rc = TPM2_RC_HANDLE; + return sandbox_tpm2_fill_buf(recv, recv_len, +tag, rc); + } + break; + default: + printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or " + "TPM2_CAP_TPM_PROPERTIES\n"); rc = TPM2_RC_HANDLE; return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); } @@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, put_unaligned_be32(capability, recv); recv += sizeof(capability); - /* Give the number of properties that follow */ - put_unaligned_be32(property_count, recv); - recv += sizeof(property_count); - - /* Fill with the properties */ - for (i = 0; i < property_count; i++) { - put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property + - i, recv); - recv += sizeof(property); - put_unaligned_be32(tpm->properties[property + i], - recv); - recv += sizeof(property); + switch (capability) { + case TPM2_CAP_PCRS: + /* Give the number of algorithms supported - just SHA256 */ + put_unaligned_be32(1, recv); + recv += sizeof(u32); + + /* Give SHA256 algorithm */ + put_unaligned_be16(TPM2_ALG_SHA256, recv); + recv += sizeof(u16); + + /* Select the PCRs supported */ + *recv = SAN