summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2023-08-29 16:58:42 -0400
committerTom Rini <[email protected]>2023-08-29 16:58:42 -0400
commitda3cb125b0e8f0625b6bba5cb3f05b70174bb5e9 (patch)
treea532f75fd88442abc3d452f40af95bb071ac9a8b
parent11cf91f755c7b1f1c8e7865743ac589bd23b7099 (diff)
parent1df1d566d21f52703511e55fadd72993a137a464 (diff)
Merge branch '2023-08-29-integrate-efi-capsule-update-better-in-to-u-boot-buildflow' into next
To quote the author: This patchset aims to bring two capsule related tasks under the U-Boot build flow. The first task is related to generation of capsules. The capsules can be generated as part of U-Boot build, and this is being achieved through binman, by adding a capsule entry type. The capsules can be generated by specifying the capsule parameters as properties under the capsule entry node. The other task is the embedding of the public key into the platform's DTB. The public key is in the form of an EFI Signature List(ESL) file and is used for capsule authentication. This is being achieved by adding the signature node containing the capsule public key in the platform's DTB. Corresponding changes have also been made to the test setup of the EFI capsule update feature. The ESL public key file was embedded into the sandbox platform's test.dtb as part of the test setup, post U-Boot build. This is now no longer needed as the embedding of the ESL happens as part of the build. Secondly, the capsules needed for testing the EFI capsule update feature were being generated through the invocation of the mkeficapsule tool. This setup has also been changed to introduce generation of these capsules through binman. The document has been updated to reflect the above changes.
-rw-r--r--.azure-pipelines.yml2
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--arch/arm/dts/nuvoton-npcm845-evb.dts2
-rw-r--r--board/sandbox/capsule_priv_key_bad.key28
-rw-r--r--board/sandbox/capsule_priv_key_good.key28
-rw-r--r--board/sandbox/capsule_pub_esl_good.eslbin0 -> 831 bytes
-rw-r--r--board/sandbox/capsule_pub_key_bad.crt19
-rw-r--r--board/sandbox/capsule_pub_key_good.crt19
-rw-r--r--configs/sandbox_defconfig1
-rw-r--r--configs/sandbox_flattree_defconfig1
-rw-r--r--configs/sandbox_noinst_defconfig2
-rw-r--r--configs/sandbox_spl_defconfig2
-rw-r--r--configs/sandbox_vpl_defconfig2
-rw-r--r--doc/develop/uefi/uefi.rst59
-rw-r--r--include/sandbox_efi_capsule.h21
-rw-r--r--lib/efi_loader/Kconfig8
-rw-r--r--lib/efi_loader/capsule_esl.dtsi.in11
-rw-r--r--scripts/Makefile.lib30
-rw-r--r--test/py/tests/test_efi_capsule/capsule_gen_binman.dts321
-rw-r--r--test/py/tests/test_efi_capsule/conftest.py175
-rw-r--r--test/py/tests/test_efi_capsule/signature.dts10
-rw-r--r--test/py/tests/test_efi_capsule/uboot_bin_env.its36
-rw-r--r--test/py/tests/test_trace.py2
-rw-r--r--tools/binman/bintool.py19
-rw-r--r--tools/binman/btool/mkeficapsule.py101
-rw-r--r--tools/binman/entries.rst64
-rw-r--r--tools/binman/etype/efi_capsule.py143
-rw-r--r--tools/binman/ftest.py118
-rw-r--r--tools/binman/test/311_capsule.dts21
-rw-r--r--tools/binman/test/312_capsule_signed.dts23
-rw-r--r--tools/binman/test/313_capsule_version.dts22
-rw-r--r--tools/binman/test/314_capsule_signed_ver.dts24
-rw-r--r--tools/binman/test/315_capsule_oemflags.dts22
-rw-r--r--tools/binman/test/316_capsule_missing_key.dts22
-rw-r--r--tools/binman/test/317_capsule_missing_index.dts20
-rw-r--r--tools/binman/test/318_capsule_missing_guid.dts19
36 files changed, 1175 insertions, 224 deletions
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 9acc4f5dbba..48cbdd41e19 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -275,7 +275,7 @@ stages:
TEST_PY_BD: "sandbox"
BUILD_ENV: "FTRACE=1 NO_LTO=1"
TEST_PY_TEST_SPEC: "trace"
- OVERRIDE: "-a CONFIG_TRACE=y -a CONFIG_TRACE_EARLY=y -a CONFIG_TRACE_EARLY_SIZE=0x01000000"
+ OVERRIDE: "-a CONFIG_TRACE=y -a CONFIG_TRACE_EARLY=y -a CONFIG_TRACE_EARLY_SIZE=0x01000000 -a CONFIG_TRACE_BUFFER_SIZE=0x02000000"
coreboot:
TEST_PY_BD: "coreboot"
TEST_PY_ID: "--id qemu"
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8f488a0c85c..6d7ffdd1bbc 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -315,7 +315,7 @@ sandbox trace_test.py:
TEST_PY_BD: "sandbox"
BUILD_ENV: "FTRACE=1 NO_LTO=1"
TEST_PY_TEST_SPEC: "trace"
- OVERRIDE: "-a CONFIG_TRACE=y -a CONFIG_TRACE_EARLY=y -a CONFIG_TRACE_EARLY_SIZE=0x01000000"
+ OVERRIDE: "-a CONFIG_TRACE=y -a CONFIG_TRACE_EARLY=y -a CONFIG_TRACE_EARLY_SIZE=0x01000000 -a CONFIG_TRACE_BUFFER_SIZE=0x02000000"
<<: *buildman_and_testpy_dfn
evb-ast2500 test.py:
diff --git a/arch/arm/dts/nuvoton-npcm845-evb.dts b/arch/arm/dts/nuvoton-npcm845-evb.dts
index 3cab7807e31..a93666cb419 100644
--- a/arch/arm/dts/nuvoton-npcm845-evb.dts
+++ b/arch/arm/dts/nuvoton-npcm845-evb.dts
@@ -354,4 +354,4 @@
&r1en_pins
&r1oen_pins
>;
-}; \ No newline at end of file
+};
diff --git a/board/sandbox/capsule_priv_key_bad.key b/board/sandbox/capsule_priv_key_bad.key
new file mode 100644
index 00000000000..2324f69ebd1
--- /dev/null
+++ b/board/sandbox/capsule_priv_key_bad.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCmPw1pGd2xNW0p
+lesRXkkek3uwUB06Nt61tnZvpMkBKt4IokqGWz1tZls+Z2CqvwOfcsPZ27cPRYSu
+xRnM3YdL4MG6SePV7i/YSNw3rq8CP8zLGtCbNIfsfsNfPQEtPBpw6+7pMJKhjqpV
+2U2UQzZEiX4qlnhLpyv2JNJag27yf0feLdJi7HnJ9xdvcXpA1DSGm4y+DDhgYeI8
+DEteEu6s0TYQfnOZSQOeJi+1/Qz0S594uFJB37MyGh/mB15ILb8gva4nA3ayHOBK
+0dd+HSiUCGYrLYO7aj+nfzQj9N1qTlzCnC1603bMczU5pkwcODg6xP0Sn11J6RYy
+y0c0qzJLAgMBAAECggEABDY2MLoew3IkBltrParAWAUUcFLi95jw92q6BkOHEJg8
+2qia1yCitPUtPodMLmOKF5x4EdgXg5sv2O8MGbWP1VtUKXGh3QJcnRnNmsZ1hXJC
+RBcrei2aVLsqf0V2Mg3+GuG8PW3vLWHyZ/Sd6afeuXEYm2Bzrw9J5rfd3dBVKm7f
+HBvIyy1ATO/2cbUaEaCLOyhxLhssTI2TIK5SjlsjFLxiQXEi6RyGfBxUCriKZykS
+krMdvYh7Tf0uYcv0STmQ5s5Rd+RhRIGCVAdsNBxxJjgBAgqqa/B+kWbcc6o2D41n
+yWjErUaBBx3t0A7oT4K4DSTYwMNDVY3fhdd+szsocQKBgQDjnm8LG4UO6OQDm6iX
+0vTQTItoAz5TU6GEjHTCfVEqiupD4LKfHhSXwp2hRyzxXO5oNTU9MQCzYd7Npes0
+oVk4Tjo3YDacNPgxqKjODu/Q+tkTH15ydzGr674+YXHfCA1uT5GKOiiF0H1FZgMa
+Dk0s+3uWX34vbL4QCu97bUhBewKBgQC6+Z0J9sClgWvvjkglJN3XhRnAacp+WgX7
+bkpgSboXIIsqeqhd1WCLeV7L1pcZgifYBMPojf5LTBqBedL1q3RuqiqQWD/bSIYN
+Oc9KCdTjksS8Zo+w+s5zDObDhW9y13H2mKwDqilYBrT4fiA62wPMf1SjEF+RSC6K
+ZrQzHO1xcQKBgAILsXnLFIYOx8XUh05eAf9BQNt9c/jxvnjffkklMS6Nsw9LHK/b
+aFn40MvbROcia64aFFFpeFUkYwk8HYIKlS+xXEqVHciHnVds6Z94eOVK69qFJKco
+tRSTeNE8tPZJLz23j1pLrYOOXSHbidmZGU53MCQo1Yx9kLO6NW7Ji6WzAoGBALP4
+lEoE80Xbn3NEdvkZ1VcfzLvCmKCqMlvjuz+Xd8HPF2VaDznSq01VFAQMmAB7obJy
+U8hC9OSxakn6Yy8JS9dBgBrUdxKxaibM4FQZxosOuMPHzMPDhniDkJPemnnmGtIL
+/nbAkW8jdYpCjO9Z5PwwC92xYuvKmNGrLgSM8ZhhAoGAfgSZTpASXubM18E3ecfw
+5z333wf9qEQgZj7i9MzByFZudyHUhv/FPW1ocUJf36Wu1dfofZg3noSL6oakrm2v
+dFDo4PoyCStuF0w9SSzpIld01ZG0t7XqphY0DmshCXIXsqr7Vb4WrbBI7KX+b3Um
+BzmROfaSud97NjQ/RA26OZk=
+-----END PRIVATE KEY-----
diff --git a/board/sandbox/capsule_priv_key_good.key b/board/sandbox/capsule_priv_key_good.key
new file mode 100644
index 00000000000..9a37f597964
--- /dev/null
+++ b/board/sandbox/capsule_priv_key_good.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCwBfaV0P1jRzS6
+13U1T+4VbuMVsxFXhwHJY5z5Fx6v+cWBf3K1ruK+7cEnW55ZHXvNE2JCkjMvISKm
+hI/DLJWIPnAus8tFdU/R2u5oJbKI+b6GbuamO/CG9HsXZ58lOC6r2ckjixxovsA9
+SFshccdIv2YrwiVsWeyFpH+rB3/+cFbrgdWpaUc1367GkU/ZCnSRDBvVvzRRI1a4
+y2NogFqbZHXHENpzWNJ3TTXhf9dwM5HFGkmX7SA43Dtazae6CB4EaUKzLYWj3+ae
+AQbdvBrupKZQz1PUKn7X6+BGaLujHthvibYppNegPvqbJ1xBbv59CQK+lRULwC05
+NYw5+sIxAgMBAAECggEAHn8h/knjpMAw/BAZP//VrYP1Nwy7u/Dpl9U43JUrXWzG
+Uc3dd2nR4id6GBIRCLqJePnbQ9JlqMwyXyxHZhbC34SF1imTVbjh9+dY99VULdQr
+NMphDrsCzLbt3pu24HFv8Jk+dniDFwi5cMSo+U3nq4xxrLIp3rBjwLHD5sNZYyEU
+9xZnj7ziTn5X8da8iRxNpyzz2kQeVemJ0ahr/IkX718bkakSFMesGkln06vH7rAs
+069SeqOPrFEbWYXI5iMktLugl3JZpzasRE48j0M42PuProgvT7jb8B35ZF7kn0jT
+MqTIHglsJRWcSY0fAb2lHSAvd2vLLVunxr9PDWZvGQKBgQDVzVTuvo1CrVrQLy+B
+tpy2k5mjR3qxAOcoWTnKcMErLe8imWWaxukODenP4XqQIX4Sl+X3BXxOqun0Klap
+FEsI7TWSHf0eULFtFj0SCgqfRR+V/nblP05eO2nFXgr5YdNa1bWf/aMHplBo4q9e
+bbAr4InUB7IGWL2cWjhOhWuJbQKBgQDSw81cBM+vGPUYH/wlxlTVgZCo2Dg2NHjt
+LUBqvOZNr21j2F+w8t1vKmqwhkqpc5HIi3pHjEA5gZLTRtmf4GQyo973I6MGn4bS
+eayOd6/+FkAi9DUD+WaF7yctJqeevav6KF2UCiz78OtCAU5Y9jFFJpuOANIztI7m
+t7ZCUpMFVQKBgFnAsP7oj3SGQbFTnaXeeztKCx04TJExx9hwXIpXe0AdMF5d9wFa
+r0tvG9Bg34rSBJLZoXhpnR2JMl2FyIuCMV219t84J6IqTdF1nH2OKZdi9TeKc28Z
+fFSirGxmZkT6hDeFr5FScLYtY2QkhWomseY5hKK1+E4hwrd4SFruN46hAoGBAJgh
+nzTBgEtqH1enlrCJhSiLmihV0dVGcNb559pjuXTvoG0GfKPT2gPowRPkCzZe5ia0
+jrHgSWd44MtCA8nEBW8MG9+VyJH6Si3Yh7ZaLB2iX+8bCL1yow8f/c44bZtGW0F5
+K3q1EZ1VW+rL2IqcQhog8P1CGHgb514f0x3yTo71AoGACGdb+Nb6lg8OSJPUcuuH
+xsWk6RhkJl9bldTleS+QT3R9zO3FvbTwnCCYJboh5Cq/jVmiA7T+fcVAyEJNHSdm
+hxbHdScuiJdNWL9+FczOkylnKH3VEdG3RS5lGdyi6r+miTMs3h8WfzGp4JINysjg
+PUFskK36qGjASfkRUn0hizQ=
+-----END PRIVATE KEY-----
diff --git a/board/sandbox/capsule_pub_esl_good.esl b/board/sandbox/capsule_pub_esl_good.esl
new file mode 100644
index 00000000000..f8cc272309b
--- /dev/null
+++ b/board/sandbox/capsule_pub_esl_good.esl
Binary files differ
diff --git a/board/sandbox/capsule_pub_key_bad.crt b/board/sandbox/capsule_pub_key_bad.crt
new file mode 100644
index 00000000000..2e8e5d58281
--- /dev/null
+++ b/board/sandbox/capsule_pub_key_bad.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDzCCAfegAwIBAgIUWw3vHYnrjoHUXytxSm2eYWzbYVAwDQYJKoZIhvcNAQEL
+BQAwFjEUMBIGA1UEAwwLVEVTVF9TSUdORVIwIBcNMjMwODA0MTgwODEyWhgPMzAw
+MzEwMDYxODA4MTJaMBYxFDASBgNVBAMMC1RFU1RfU0lHTkVSMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEApj8NaRndsTVtKZXrEV5JHpN7sFAdOjbetbZ2
+b6TJASreCKJKhls9bWZbPmdgqr8Dn3LD2du3D0WErsUZzN2HS+DBuknj1e4v2Ejc
+N66vAj/MyxrQmzSH7H7DXz0BLTwacOvu6TCSoY6qVdlNlEM2RIl+KpZ4S6cr9iTS
+WoNu8n9H3i3SYux5yfcXb3F6QNQ0hpuMvgw4YGHiPAxLXhLurNE2EH5zmUkDniYv
+tf0M9EufeLhSQd+zMhof5gdeSC2/IL2uJwN2shzgStHXfh0olAhmKy2Du2o/p380
+I/Tdak5cwpwtetN2zHM1OaZMHDg4OsT9Ep9dSekWMstHNKsySwIDAQABo1MwUTAd
+BgNVHQ4EFgQUm9b8SnF811nweXSfGisfpzUHGwgwHwYDVR0jBBgwFoAUm9b8SnF8
+11nweXSfGisfpzUHGwgwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
+AQEAaOZFOcQzF1MRekcBmIZMaHSWYxOUrVLzBNSNhFD8muYiUAAufrkyTUq0Mmat
+w5hAnJ34VGpU1wxQlr/uwH7wpZZnGuj10rAp3tqES0g24AeH1bC9wmRs+rD6dcZR
+YmZq6FxtV7Cv3pQX7lhDYbcBj2za3YT6I1+yczskAHR6KYYuJzKJ7XRVCL7ZlYRX
+pUMZBQq2eAVWlW/c5iDT3KoGZUD9Of71F7qyUAqMMYafeDxguDz7gKstoXVCklQ+
+I4C7JKmRbrRvMgXx6O1clGhAsRZ0nNAtzi7XT5tD27qFwIPgwv48RWgsmPtzE03S
+YGQ5WhYMdHOOjWmcV6MDkCpiSA==
+-----END CERTIFICATE-----
diff --git a/board/sandbox/capsule_pub_key_good.crt b/board/sandbox/capsule_pub_key_good.crt
new file mode 100644
index 00000000000..82d8576a648
--- /dev/null
+++ b/board/sandbox/capsule_pub_key_good.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDzCCAfegAwIBAgIUUzrWhMi7oPFshQP6eFlccqf7exswDQYJKoZIhvcNAQEL
+BQAwFjEUMBIGA1UEAwwLVEVTVF9TSUdORVIwIBcNMjMwODA0MTgwNzQyWhgPMzAw
+MzEwMDYxODA3NDJaMBYxFDASBgNVBAMMC1RFU1RfU0lHTkVSMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsAX2ldD9Y0c0utd1NU/uFW7jFbMRV4cByWOc
++Rcer/nFgX9yta7ivu3BJ1ueWR17zRNiQpIzLyEipoSPwyyViD5wLrPLRXVP0dru
+aCWyiPm+hm7mpjvwhvR7F2efJTguq9nJI4scaL7APUhbIXHHSL9mK8IlbFnshaR/
+qwd//nBW64HVqWlHNd+uxpFP2Qp0kQwb1b80USNWuMtjaIBam2R1xxDac1jSd001
+4X/XcDORxRpJl+0gONw7Ws2nuggeBGlCsy2Fo9/mngEG3bwa7qSmUM9T1Cp+1+vg
+Rmi7ox7Yb4m2KaTXoD76mydcQW7+fQkCvpUVC8AtOTWMOfrCMQIDAQABo1MwUTAd
+BgNVHQ4EFgQUHvG7Xchqzwdggky+oyzlpNem8UowHwYDVR0jBBgwFoAUHvG7Xchq
+zwdggky+oyzlpNem8UowDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
+AQEAUn1ncSqeXbQAHNrVOFldLwu70hNlMxf2z4EfH2M7vJgrpwkRuIFw7PXNITBh
+CImd/ghm5NGFysrK7BwdHkFvUXZV3rE93BhcLC9leWfky33kW9olIzpE14i5FfBn
+ABmaokPhOrzAneGzU35sZHNotlqOrzgpKVkpOWrykhYZ5Qjk8Sz0xvzuG8TJc20s
+2og+W8Rm2u/xI9xPxtFbq9vUjvFS35o1pm+vkzpgNdo4YS1PG37BW/aopsooLSk7
+9Rxv5vzNXtQqeZ5qBdKbAVh3OsgqwigTmXVvOX3xpy9r9qiimhaISxCt83RZ7wQW
+I19t9pXyxAi6u7MRhJZlAeH/3w==
+-----END CERTIFICATE-----
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index a57ab23d9a2..0f01471367d 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -340,6 +340,7 @@ CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
CONFIG_EFI_CAPSULE_ON_DISK=y
CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
CONFIG_EFI_CAPSULE_AUTHENTICATE=y
+CONFIG_EFI_CAPSULE_ESL_FILE="board/sandbox/capsule_pub_esl_good.esl"
CONFIG_EFI_SECURE_BOOT=y
CONFIG_TEST_FDTDEC=y
CONFIG_UNIT_TEST=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index c20015db47b..db916e6c4e9 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -226,6 +226,7 @@ CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
CONFIG_EFI_CAPSULE_ON_DISK=y
CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y
CONFIG_EFI_CAPSULE_AUTHENTICATE=y
+CONFIG_EFI_CAPSULE_ESL_FILE="board/sandbox/capsule_pub_esl_good.esl"
CONFIG_UNIT_TEST=y
CONFIG_UT_TIME=y
CONFIG_UT_DM=y
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig
index f6e351961e9..ee04fbbc2e9 100644
--- a/configs/sandbox_noinst_defconfig
+++ b/configs/sandbox_noinst_defconfig
@@ -236,6 +236,8 @@ CONFIG_TPM=y
CONFIG_LZ4=y
CONFIG_ZSTD=y
CONFIG_ERRNO_STR=y
+CONFIG_EFI_CAPSULE_ON_DISK=y
+CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
CONFIG_UNIT_TEST=y
CONFIG_SPL_UNIT_TEST=y
CONFIG_UT_TIME=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index 7e6ee936769..69b413382a1 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -244,6 +244,8 @@ CONFIG_LZ4=y
CONFIG_ZSTD=y
CONFIG_ERRNO_STR=y
CONFIG_SPL_HEXDUMP=y
+CONFIG_EFI_CAPSULE_ON_DISK=y
+CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
CONFIG_UNIT_TEST=y
CONFIG_SPL_UNIT_TEST=y
CONFIG_UT_TIME=y
diff --git a/configs/sandbox_vpl_defconfig b/configs/sandbox_vpl_defconfig
index 9ac800a93c0..27354b8b5ed 100644
--- a/configs/sandbox_vpl_defconfig
+++ b/configs/sandbox_vpl_defconfig
@@ -255,6 +255,8 @@ CONFIG_LZ4=y
CONFIG_ZSTD=y
# CONFIG_VPL_LZMA is not set
CONFIG_ERRNO_STR=y
+CONFIG_EFI_CAPSULE_ON_DISK=y
+CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
CONFIG_UNIT_TEST=y
CONFIG_SPL_UNIT_TEST=y
CONFIG_UT_TIME=y
diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst
index a7a41f2facf..68f9b332d15 100644
--- a/doc/develop/uefi/uefi.rst
+++ b/doc/develop/uefi/uefi.rst
@@ -318,6 +318,9 @@ Run the following command
--guid <image GUID> \
<capsule_file_name>
+Capsule with firmware version
+*****************************
+
The UEFI specification does not define the firmware versioning mechanism.
EDK II reference implementation inserts the FMP Payload Header right before
the payload. It coutains the fw_version and lowest supported version,
@@ -345,6 +348,43 @@ add --fw-version option in mkeficapsule tool.
If the --fw-version option is not set, FMP Payload Header is not inserted
and fw_version is set as 0.
+Capsule Generation through binman
+*********************************
+
+Support has also been added to generate capsules during U-Boot build
+through binman. This requires the platform's DTB to be populated with
+the capsule entry nodes for binman. The capsules then can be generated
+by specifying the capsule parameters as properties in the capsule
+entry node.
+
+Check the test/py/tests/test_efi_capsule/capsule_gen_binman.dts file
+as reference for how a typical binman node for capsule generation
+looks like. For generating capsules as part of the platform's build, a
+capsule node would then have to be included into the platform's
+devicetree.
+
+A typical binman node for generating a capsule would look like::
+
+ capsule {
+ filename = "u-boot.capsule";
+ efi-capsule {
+ image-index = <0x1>;
+ image-guid = "09d7cf52-0720-4710-91d1-08469b7fe9c8";
+
+ u-boot {
+ };
+ };
+ };
+
+In the above example, a capsule file named u-boot.capsule will be
+generated with u-boot.bin as it's input payload. The capsule
+generation parameters like image-index and image-guid are being
+specified as properties. Similarly, other properties like the private
+and public key certificate can be specified for generating signed
+capsules. Refer :ref:`etype_efi_capsule` for documentation about the
+efi-capsule binman entry type, which describes all the properties that
+can be specified.
+
Performing the update
*********************
@@ -522,20 +562,11 @@ and used by the steps highlighted below.
...
}
-You can do step-4 manually with
-
-.. code-block:: console
-
- $ dtc -@ -I dts -O dtb -o signature.dtbo signature.dts
- $ fdtoverlay -i orig.dtb -o new.dtb -v signature.dtbo
-
-where signature.dts looks like::
-
- &{/} {
- signature {
- capsule-key = /incbin/("CRT.esl");
- };
- };
+You can perform step-4 through the Kconfig symbol
+CONFIG_EFI_CAPSULE_ESL_FILE. This symbol points to the esl file
+generated in step-2. Once the symbol has been populated with the path
+to the esl file, it will automatically get embedded into the
+platform's dtb as part of U-Boot build.
Anti-rollback Protection
************************
diff --git a/include/sandbox_efi_capsule.h b/include/sandbox_efi_capsule.h
new file mode 100644
index 00000000000..3e288e8a84a
--- /dev/null
+++ b/include/sandbox_efi_capsule.h
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#if !defined(_SANDBOX_EFI_CAPSULE_H_)
+#define _SANDBOX_EFI_CAPSULE_H_
+
+#define SANDBOX_UBOOT_IMAGE_GUID "09d7cf52-0720-4710-91d1-08469b7fe9c8"
+#define SANDBOX_UBOOT_ENV_IMAGE_GUID "5a7021f5-fef2-48b4-aaba-832e777418c0"
+#define SANDBOX_FIT_IMAGE_GUID "3673b45d-6a7c-46f3-9e60-adabb03f7937"
+#define SANDBOX_INCORRECT_GUID "058b7d83-50d5-4c47-a195-60d86ad341c4"
+
+#define UBOOT_FIT_IMAGE "u-boot_bin_env.itb"
+
+#define CAPSULE_PRIV_KEY "capsule_priv_key_good.key"
+#define CAPSULE_PUB_KEY "capsule_pub_key_good.crt"
+#define CAPSULE_INVAL_KEY "capsule_priv_key_bad.key"
+#define CAPSULE_INVAL_PUB_KEY "capsule_pub_key_bad.crt"
+
+#endif /* _SANDBOX_EFI_CAPSULE_H_ */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 9989e3f384e..d20aaab6dba 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -272,6 +272,14 @@ config EFI_CAPSULE_MAX
Select the max capsule index value used for capsule report
variables. This value is used to create CapsuleMax variable.
+config EFI_CAPSULE_ESL_FILE
+ string "Path to the EFI Signature List File"
+ depends on EFI_CAPSULE_AUTHENTICATE
+ help
+ Provides the path to the EFI Signature List file which will
+ be embedded in the platform's device tree and used for
+ capsule authentication at the time of capsule update.
+
config EFI_DEVICE_PATH_TO_TEXT
bool "Device path to text protocol"
default y
diff --git a/lib/efi_loader/capsule_esl.dtsi.in b/lib/efi_loader/capsule_esl.dtsi.in
new file mode 100644
index 00000000000..61a9f2b25e9
--- /dev/null
+++ b/lib/efi_loader/capsule_esl.dtsi.in
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+/**
+ * Devicetree file with the public key EFI Signature List(ESL)
+ * node. This file is used to generate the dtsi file to be
+ * included into the DTB.
+*/
+/ {
+ signature {
+ capsule-key = /incbin/("ESL_BIN_FILE");
+ };
+};
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index f5ab7af0f45..8dc6ec82cd5 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -179,10 +179,13 @@ ifdef DEVICE_TREE_DEBUG
u_boot_dtsi_options_debug = $(warning $(u_boot_dtsi_options_raw))
endif
-# We use the first match
-u_boot_dtsi = $(strip $(u_boot_dtsi_options_debug) \
+# We use the first match to be included
+dtsi_include_list = $(strip $(u_boot_dtsi_options_debug) \
$(notdir $(firstword $(u_boot_dtsi_options))))
+# The CONFIG_DEVICE_TREE_INCLUDES also need to be included
+dtsi_include_list += $(CONFIG_DEVICE_TREE_INCLUDES)
+
# Modified for U-Boot
dtc_cpp_flags = -Wp,-MD,$(depfile).pre.tmp -nostdinc \
$(UBOOTINCLUDE) \
@@ -320,8 +323,8 @@ quiet_cmd_dtc = DTC $@
# Bring in any U-Boot-specific include at the end of the file
# And finally any custom .dtsi fragments specified with CONFIG_DEVICE_TREE_INCLUDES
cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
- (cat $<; $(if $(u_boot_dtsi),echo '$(pound)include "$(u_boot_dtsi)"')) > $(pre-tmp); \
- $(foreach f,$(subst $(quote),,$(CONFIG_DEVICE_TREE_INCLUDES)), \
+ (cat $< > $(pre-tmp)); \
+ $(foreach f,$(subst $(quote),,$(dtsi_include_list)), \
echo '$(pound)include "$(f)"' >> $(pre-tmp);) \
$(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $(pre-tmp) ; \
$(DTC) -O dtb -o $@ -b 0 \
@@ -331,7 +334,24 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
; \
sed "s:$(pre-tmp):$(<):" $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
-$(obj)/%.dtb: $(src)/%.dts $(DTC) FORCE
+quiet_cmd_capsule_esl_gen = CAPSULE_ESL_GEN $@
+cmd_capsule_esl_gen = \
+ $(shell sed "s:ESL_BIN_FILE:$(capsule_esl_path):" $(capsule_esl_input_file) > $@)
+
+$(obj)/.capsule_esl.dtsi: FORCE
+ $(call cmd_capsule_esl_gen)
+
+capsule_esl_input_file=$(srctree)/lib/efi_loader/capsule_esl.dtsi.in
+capsule_esl_dtsi = .capsule_esl.dtsi
+capsule_esl_path=$(abspath $(srctree)/$(subst $(quote),,$(CONFIG_EFI_CAPSULE_ESL_FILE)))
+
+ifdef CONFIG_EFI_CAPSULE_AUTHENTICATE
+dtsi_include_list += $(capsule_esl_dtsi)
+endif
+
+dtsi_include_list_deps = $(addprefix $(obj)/,$(subst $(quote),,$(dtsi_include_list)))
+
+$(obj)/%.dtb: $(src)/%.dts $(DTC) $(dtsi_include_list_deps) FORCE
$(call if_changed_dep,dtc)
pre-tmp = $(subst $(comma),_,$(dot-target).pre.tmp)
diff --git a/test/py/tests/test_efi_capsule/capsule_gen_binman.dts b/test/py/tests/test_efi_capsule/capsule_gen_binman.dts
new file mode 100644
index 00000000000..e8a18585092
--- /dev/null
+++ b/test/py/tests/test_efi_capsule/capsule_gen_binman.dts
@@ -0,0 +1,321 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Devicetree for capsule generation through binman
+ */
+
+/dts-v1/;
+
+#include <sandbox_efi_capsule.h>
+
+/ {
+ binman: binman {
+ multiple-images;
+ };
+};
+
+&binman {
+ itb {
+ filename = UBOOT_FIT_IMAGE;
+
+ fit {
+ description = "Automatic U-Boot environment update";
+ #address-cells = <2>;
+
+ images {
+ u-boot-bin {
+ description = "U-Boot binary on SPI Flash";
+ compression = "none";
+ type = "firmware";
+ arch = "sandbox";
+ load = <0>;
+ text {
+ text = "u-boot:New";
+ };
+
+ hash-1 {
+ algo = "sha1";
+ };
+ };
+ u-boot-env {
+ description = "U-Boot environment on SPI Flash";
+ compression = "none";
+ type = "firmware";
+ arch = "sandbox";
+ load = <0>;
+ text {
+ text = "u-boot-env:New";
+ };
+
+ hash-1 {
+ algo = "sha1";
+ };
+ };
+ };
+ };
+ };
+
+ capsule1 {
+ filename = "Test01";
+ efi-capsule {
+ image-index = <0x1>;
+ image-guid = SANDBOX_UBOOT_IMAGE_GUID;
+
+ text {
+ text = "u-boot:New";
+ };
+ };
+ };
+
+ capsule2 {
+ filename = "Test02";
+ efi-capsule {
+ image-index = <0x2>;
+ image-guid = SANDBOX_UBOOT_ENV_IMAGE_GUID;
+
+ text {
+ text = "u-boot-env:New";
+ };
+ };
+ };
+
+ capsule3 {
+ filename = "Test03";
+ efi-capsule {
+ image-index = <0x1>;
+ image-guid = SANDBOX_INCORRECT_GUID;
+
+ text {
+ text = "u-boot:New";
+ };
+ };
+ };
+
+ capsule4 {
+ filename = "Test04";
+ efi-capsule {
+ image-index = <0x1>;
+ image-guid = SANDBOX_FIT_IMAGE_GUID;
+
+ blob {
+ filename = UBOOT_FIT_IMAGE;
+ };
+ };
+ };
+
+ capsule5 {
+ filename = "Test05";
+ efi-capsule {
+ image-index = <0x1>;
+ image-guid = SANDBOX_INCORRECT_GUID;
+
+ blob {
+ filename = UBOOT_FIT_IMAGE;
+ };
+ };
+ };
+
+ capsule6 {
+ filename = "Test101";
+ efi-capsule {
+ image-index = <0x1>;
+ fw-version = <0x5>;
+ image-guid = SANDBOX_UBOOT_IMAGE_GUID;
+
+ text {
+ text = "u-boot:New";
+ };
+ };
+ };
+
+ capsule7 {
+ filename = "Test102";
+ efi-capsule {
+ image-index = <0x2>;
+ fw-version = <0xa>;
+ image-guid = SANDBOX_UBOOT_ENV_IMAGE_GUID;
+
+ text {
+ text = "u-boot-env:New";
+ };
+ };
+ };
+
+ capsule8 {
+ filename = "Test103";
+ efi-capsule {
+ image-index = <0x1>;
+ fw-version = <0x2>;
+ image-guid = SANDBOX_UBOOT_IMAGE_GUID;
+
+ text {
+ text = "u-boot:New";
+ };
+ };
+ };
+
+ capsule9 {
+ filename = "Test104";
+ efi-capsule {
+ image-index = <0x1>;
+ fw-version = <0x5>;
+ image-guid = SANDBOX_FIT_IMAGE_GUID;
+
+ blob {
+ filename = UBOOT_FIT_IMAGE;
+ };
+ };
+ };
+
+ capsule10 {
+ filename = "Test105";
+ efi-capsule {
+ image-index = <0x1>;
+ fw-version = <0x2>;
+ image-guid = SANDBOX_FIT_IMAGE_GUID;
+
+ blob {
+ filename = UBOOT_FIT_IMAGE;
+ };
+ };
+ };
+
+ capsule11 {
+ filename = "Test11";
+ efi-capsule {
+ image-index = <0x1>;
+ image-guid = SANDBOX_UBOOT_IMAGE_GUID;
+ private-key = CAPSULE_PRIV_KEY;
+ public-key-cert = CAPSULE_PUB_KEY;
+ monotonic-count = <0x1>;
+
+ text {
+ text = "u-boot:New";
+ };
+ };
+ };
+
+ capsule12 {
+ filename = "Test12";
+ efi-capsule {
+ image-index = <0x1>;
+ image-guid = SANDBOX_UBOOT_IMAGE_GUID;
+ private-key = CAPSULE_INVAL_KEY;
+ public-key-cert = CAPSULE_INVAL_PUB_KEY;
+ monotonic-count = <0x1>;
+
+ text {
+ text = "u-boot:New";
+ };
+ };
+ };
+
+ capsule13 {
+ filename = "Test13";
+ efi-capsule {
+ image-index = <0x1>;
+ image-guid = SANDBOX_FIT_IMAGE_GUID;
+ private-key = CAPSULE_PRIV_KEY;
+ public-key-cert = CAPSULE_PUB_KEY;
+ monotonic-count = <0x1>;
+
+ blob {
+ filename = UBOOT_FIT_IMAGE;
+ };
+ };
+ };
+
+ capsule14 {
+ filename = "Test14";
+ efi-capsule {
+ image-index = <0x1>;
+ image-guid = SANDBOX_FIT_IMAGE_GUID;
+ private-key = CAPSULE_INVAL_KEY;
+ public-key-cert = CAPSULE_INVAL_PUB_KEY;
+ monotonic-count = <0x1>;
+
+ blob {
+ filename = UBOOT_FIT_IMAGE;
+ };
+ };
+ };
+
+ capsule15 {
+ filename = "Test111";
+ efi-capsule {
+ image-index = <0x1>;
+ fw-version = <0x5>;
+ image-guid = SANDBOX_UBOOT_IMAGE_GUID;
+ private-key = CAPSULE_PRIV_KEY;
+ public-key-cert = CAPSULE_PUB_KEY;
+ monotonic-count = <0x1>;
+
+ text {
+ text = "u-boot:New";
+ };
+ };
+ };
+
+ capsule16 {
+ filename = "Test112";
+ efi-capsule {
+ image-index = <0x2>;
+ fw-version = <0xa>;
+ image-guid = SANDBOX_UBOOT_ENV_IMAGE_GUID;
+ private-key = CAPSULE_PRIV_KEY;
+ public-key-cert = CAPSULE_PUB_KEY;
+ monotonic-count = <0x1>;
+
+ text {
+ text = "u-boot-env:New";
+ };
+ };
+ };
+
+ capsule17 {
+ filename = "Test113";
+ efi-capsule {
+ image-index = <0x1>;
+ fw-version = <0x2>;
+ image-guid = SANDBOX_UBOOT_IMAGE_GUID;
+ private-key = CAPSULE_PRIV_KEY;
+ public-key-cert = CAPSULE_PUB_KEY;
+ monotonic-count = <0x1>;
+
+ text {
+ text = "u-boot:New";
+ };
+ };
+ };
+
+ capsule18 {
+ filename = "Test114";
+ efi-capsule {
+ image-index = <0x1>;
+ fw-version = <0x5>;
+ image-guid = SANDBOX_FIT_IMAGE_GUID;
+ private-key = CAPSULE_PRIV_KEY;
+ public-key-cert = CAPSULE_PUB_KEY;
+ monotonic-count = <0x1>;
+
+ blob {
+ filename = UBOOT_FIT_IMAGE;
+ };
+ };
+ };
+
+ capsule19 {
+ filename = "Test115";
+ efi-capsule {
+ image-index = <0x1>;
+ fw-version = <0x2>;
+ image-guid = SANDBOX_FIT_IMAGE_GUID;
+ private-key = CAPSULE_PRIV_KEY;
+ public-key-cert = CAPSULE_PUB_KEY;
+ monotonic-count = <0x1>;
+
+ blob {
+ filename = UBOOT_FIT_IMAGE;
+ };
+ };
+ };
+};
diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py
index 054be1ee971..dd41da9284e 100644
--- a/test/py/tests/test_efi_capsule/conftest.py
+++ b/test/py/tests/test_efi_capsule/conftest.py
@@ -4,6 +4,8 @@
"""Fixture for UEFI capsule test."""
+import os
+
from subprocess import call, check_call, CalledProcessError
import pytest
from capsule_defs import CAPSULE_DATA_DIR, CAPSULE_INSTALL_DIR, EFITOOLS_PATH
@@ -34,40 +36,31 @@ def efi_capsule_data(request, u_boot_config):
capsule_auth_enabled = u_boot_config.buildconfig.get(
'config_efi_capsule_authenticate')
+ key_dir = u_boot_config.source_dir + '/board/sandbox'
if capsule_auth_enabled:
- # Create private key (SIGNER.key) and certificate (SIGNER.crt)
- check_call('cd %s; '
- 'openssl req -x509 -sha256 -newkey rsa:2048 '
- '-subj /CN=TEST_SIGNER/ -keyout SIGNER.key '
- '-out SIGNER.crt -nodes -days 365'
- % data_dir, shell=True)
- check_call('cd %s; %scert-to-efi-sig-list SIGNER.crt SIGNER.esl'
- % (data_dir, EFITOOLS_PATH), shell=True)
-
- # Update dtb adding capsule certificate
- check_call('cd %s; '
- 'cp %s/test/py/tests/test_efi_capsule/signature.dts .'
- % (data_dir, u_boot_config.source_dir), shell=True)
- check_call('cd %s; '
- 'dtc -@ -I dts -O dtb -o signature.dtbo signature.dts; '
- 'fdtoverlay -i %s/arch/sandbox/dts/test.dtb '
- '-o test_sig.dtb signature.dtbo'
- % (data_dir, u_boot_config.build_dir), shell=True)
+ # Get the keys from the board directory
+ check_call('cp %s/capsule_priv_key_good.key %s/SIGNER.key'
+ % (key_dir, data_dir), shell=True)
+ check_call('cp %s/capsule_pub_key_good.crt %s/SIGNER.crt'
+ % (key_dir, data_dir), shell=True)
+ check_call('cp %s/capsule_pub_esl_good.esl %s/SIGNER.esl'
+ % (key_dir, data_dir), shell=True)
- # Create *malicious* private key (SIGNER2.key) and certificate
- # (SIGNER2.crt)
- check_call('cd %s; '
- 'openssl req -x509 -sha256 -newkey rsa:2048 '
- '-subj /CN=TEST_SIGNER/ -keyout SIGNER2.key '
- '-out SIGNER2.crt -nodes -days 365'
- % data_dir, shell=True)
+ check_call('cp %s/capsule_priv_key_bad.key %s/SIGNER2.key'
+ % (key_dir, data_dir), shell=True)
+ check_call('cp %s/capsule_pub_key_bad.crt %s/SIGNER2.crt'
+ % (key_dir, data_dir), shell=True)
# Update dtb to add the version information
check_call('cd %s; '
'cp %s/test/py/tests/test_efi_capsule/version.dts .'
% (data_dir, u_boot_config.source_dir), shell=True)
+
if capsule_auth_enabled:
check_call('cd %s; '
+ 'cp %s/arch/sandbox/dts/test.dtb test_sig.dtb'
+ % (data_dir, u_boot_config.build_dir), shell=True)
+ check_call('cd %s; '
'dtc -@ -I dts -O dtb -o version.dtbo version.dts; '
'fdtoverlay -i test_sig.dtb '
'-o test_ver.dtb version.dtbo'
@@ -79,132 +72,20 @@ def efi_capsule_data(request, u_boot_config):
'-o test_ver.dtb version.dtbo'
% (data_dir, u_boot_config.build_dir), shell=True)
- # Create capsule files
# two regions: one for u-boot.bin and the other for u-boot.env
check_call('cd %s; echo -n u-boot:Old > u-boot.bin.old; echo -n u-boot:New > u-boot.bin.new; echo -n u-boot-env:Old > u-boot.env.old; echo -n u-boot-env:New > u-boot.env.new' % data_dir,
shell=True)
- check_call('sed -e \"s?BINFILE1?u-boot.bin.new?\" -e \"s?BINFILE2?u-boot.env.new?\" %s/test/py/tests/test_efi_capsule/uboot_bin_env.its > %s/uboot_bin_env.its' %
- (u_boot_config.source_dir, data_dir),
- shell=True)
- check_call('cd %s; %s/tools/mkimage -f uboot_bin_env.its uboot_bin_env.itb' %
- (data_dir, u_boot_config.build_dir),
- shell=True)
- check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 u-boot.bin.new Test01' %
- (data_dir, u_boot_config.build_dir),
- shell=True)
- check_call('cd %s; %s/tools/mkeficapsule --index 2 --guid 5A7021F5-FEF2-48B4-AABA-832E777418C0 u-boot.env.new Test02' %
- (data_dir, u_boot_config.build_dir),
- shell=True)
- check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 058B7D83-50D5-4C47-A195-60D86AD341C4 u-boot.bin.new Test03' %
- (data_dir, u_boot_config.build_dir),
- shell=True)
- check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 uboot_bin_env.itb Test04' %
- (data_dir, u_boot_config.build_dir),
- shell=True)
- check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 058B7D83-50D5-4C47-A195-60D86AD341C4 uboot_bin_env.itb Test05' %
- (data_dir, u_boot_config.build_dir),
- shell=True)
- check_call('cd %s; %s/tools/mkeficapsule --index 1 --fw-version 5 '
- '--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 u-boot.bin.new Test101' %
- (data_dir, u_boot_config.build_dir),
- shell=True)
- check_call('cd %s; %s/tools/mkeficapsule --index 2 --fw-version 10 '
- '--guid 5A7021F5-FEF2-48B4-AABA-832E777418C0 u-boot.env.new Test102' %
- (data_dir, u_boot_config.build_dir),
- shell=True)
- check_call('cd %s; %s/tools/mkeficapsule --index 1 --fw-version 2 '
- '--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 u-boot.bin.new Test103' %
- (data_dir, u_boot_config.build_dir),
- shell=True)
- check_call('cd %s; %s/tools/mkeficapsule --index 1 --fw-version 5 '
- '--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 uboot_bin_env.itb Test104' %
- (data_dir, u_boot_config.build_dir),
- shell=True)
- check_call('cd %s; %s/tools/mkeficapsule --index 1 --fw-version 2 '
- '--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 uboot_bin_env.itb Test105' %
- (data_dir, u_boot_config.build_dir),
- shell=True)
- if capsule_auth_enabled:
- # raw firmware signed with proper key
- check_call('cd %s; '
- '%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
- '--private-key SIGNER.key --certificate SIGNER.crt '
- '--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 '
- 'u-boot.bin.new Test11'
- % (data_dir, u_boot_config.build_dir),
- shell=True)
- # raw firmware signed with *mal* key
- check_call('cd %s; '
- '%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
- '--private-key SIGNER2.key '
- '--certificate SIGNER2.crt '
- '--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 '
- 'u-boot.bin.new Test12'
- % (data_dir, u_boot_config.build_dir),
- shell=True)
- # FIT firmware signed with proper key
- check_call('cd %s; '
- '%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
- '--private-key SIGNER.key --certificate SIGNER.crt '
- '--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 '
- 'uboot_bin_env.itb Test13'
- % (data_dir, u_boot_config.build_dir),
- shell=True)
- # FIT firmware signed with *mal* key
- check_call('cd %s; '
- '%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
- '--private-key SIGNER2.key '
- '--certificate SIGNER2.crt '
- '--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 '
- 'uboot_bin_env.itb Test14'
- % (data_dir, u_boot_config.build_dir),
- shell=True)
- # raw firmware signed with proper key with version information
- check_call('cd %s; '
- '%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
- '--fw-version 5 '
- '--private-key SIGNER.key --certificate SIGNER.crt '
- '--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 '
- 'u-boot.bin.new Test111'
- % (data_dir, u_boot_config.build_dir),
- shell=True)
- # raw firmware signed with proper key with version information
- check_call('cd %s; '
- '%s/tools/mkeficapsule --index 2 --monotonic-count 1 '
- '--fw-version 10 '
- '--private-key SIGNER.key --certificate SIGNER.crt '
- '--guid 5A7021F5-FEF2-48B4-AABA-832E777418C0 '
- 'u-boot.env.new Test112'
- % (data_dir, u_boot_config.build_dir),
- shell=True)
- # raw firmware signed with proper key with lower version information
- check_call('cd %s; '
- '%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
- '--fw-version 2 '
- '--private-key SIGNER.key --certificate SIGNER.crt '
- '--guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 '
- 'u-boot.bin.new Test113'
- % (data_dir, u_boot_config.build_dir),
- shell=True)
- # FIT firmware signed with proper key with version information
- check_call('cd %s; '
- '%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
- '--fw-version 5 '
- '--private-key SIGNER.key --certificate SIGNER.crt '
- '--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 '
- 'uboot_bin_env.itb Test114'
- % (data_dir, u_boot_config.build_dir),
- shell=True)
- # FIT firmware signed with proper key with lower version information
- check_call('cd %s; '
- '%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
- '--fw-version 2 '
- '--private-key SIGNER.key --certificate SIGNER.crt '
- '--guid 3673B45D-6A7C-46F3-9E60-ADABB03F7937 '
- 'uboot_bin_env.itb Test115'
- % (data_dir, u_boot_config.build_dir),
- shell=True)
+ pythonpath = os.environ.get('PYTHONPATH', '')
+ os.environ['PYTHONPATH'] = pythonpath + ':' + '%s/scripts/dtc/pylibfdt' % u_boot_config.build_dir
+ check_call('cd %s; '
+ 'cc -E -I %s/include -x assembler-with-cpp -o capsule_gen_tmp.dts %s/test/py/tests/test_efi_capsule/capsule_gen_binman.dts; '
+ 'dtc -I dts -O dtb capsule_gen_tmp.dts -o capsule_binman.dtb;'
+ % (data_dir, u_boot_config.source_dir, u_boot_config.source_dir), shell=True)
+ check_call('cd %s; '
+ './tools/binman/binman --toolpath %s/tools build -u -d %s/capsule_binman.dtb -O %s -m --allow-missing -I %s -I ./board/sandbox -I ./arch/sandbox/dts'
+ % (u_boot_config.source_dir, u_boot_config.build_dir, data_dir, data_dir, data_dir), shell=True)
+ os.environ['PYTHONPATH'] = pythonpath
# Create a disk image with EFI system partition
check_call('virt-make-fs --partition=gpt --size=+1M --type=vfat %s %s' %
diff --git a/test/py/tests/test_efi_capsule/signature.dts b/test/py/tests/test_efi_capsule/signature.dts
deleted file mode 100644
index 078cfc76c93..00000000000
--- a/test/py/tests/test_efi_capsule/signature.dts
+++ /dev/null
@@ -1,10 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-/dts-v1/;
-/plugin/;
-
-&{/} {
- signature {
- capsule-key = /incbin/("SIGNER.esl");
- };
-};
diff --git a/test/py/tests/test_efi_capsule/uboot_bin_env.its b/test/py/tests/test_efi_capsule/uboot_bin_env.its
deleted file mode 100644
index fc659074811..00000000000
--- a/test/py/tests/test_efi_capsule/uboot_bin_env.its
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Automatic software update for U-Boot
- * Make sure the flashing addresses ('load' prop) is correct for your board!
- */
-
-/dts-v1/;
-
-/ {
- description = "Automatic U-Boot environment update";
- #address-cells = <2>;
-
- images {
- u-boot-bin {
- description = "U-Boot binary on SPI Flash";
- data = /incbin/("BINFILE1");
- compression = "none";
- type = "firmware";
- arch = "sandbox";
- load = <0>;
- hash-1 {
- algo = "sha1";
- };
- };
- u-boot-env {
- description = "U-Boot environment on SPI Flash";
- data = /incbin/("BINFILE2");
- compression = "none";
- type = "firmware";
- arch = "sandbox";
- load = <0>;
- hash-1 {
- algo = "sha1";
- };
- };
- };
-};
diff --git a/test/py/tests/test_trace.py b/test/py/tests/test_trace.py
index ac3e95925e9..ad2250920d7 100644
--- a/test/py/tests/test_trace.py
+++ b/test/py/tests/test_trace.py
@@ -61,7 +61,7 @@ def collect_trace(cons):
# Read out the trace data
addr = 0x02000000
- size = 0x01000000
+ size = 0x02000000
out = cons.run_command(f'trace calls {addr:x} {size:x}')
print(out)
fname = os.path.join(TMPDIR, 'trace')
diff --git a/tools/binman/bintool.py b/tools/binman/bintool.py
index 0b0f56dbbba..3c4ad1adbb9 100644
--- a/tools/binman/bintool.py
+++ b/tools/binman/bintool.py
@@ -328,7 +328,7 @@ class Bintool:
return result.stdout
@classmethod
- def build_from_git(cls, git_repo, make_target, bintool_path, flags=None):
+ def build_from_git(cls, git_repo, make_targets, bintool_path, flags=None):
"""Build a bintool from a git repo
This clones the repo in a temporary directory, builds it with 'make',
@@ -336,7 +336,8 @@ class Bintool:
Args:
git_repo (str): URL of git repo
- make_target (str): Target to pass to 'make' to build the tool
+ make_targets (list of str): List of targets to pass to 'make' to build
+ the tool
bintool_path (str): Relative path of the tool in the repo, after
build is complete
flags (list of str): Flags or variables to pass to make, or None
@@ -350,12 +351,14 @@ class Bintool:
tmpdir = tempfile.mkdtemp(prefix='binmanf.')
print(f"- clone git repo '{git_repo}' to '{tmpdir}'")
tools.run('git', 'clone', '--depth', '1', git_repo, tmpdir)
- print(f"- build target '{make_target}'")
- cmd = ['make', '-C', tmpdir, '-j', f'{multiprocessing.cpu_count()}',
- make_target]
- if flags:
- cmd += flags
- tools.run(*cmd)
+ for target in make_targets:
+ print(f"- build target '{target}'")
+ cmd = ['make', '-C', tmpdir, '-j', f'{multiprocessing.cpu_count()}',
+ target]
+ if flags:
+ cmd += flags
+ tools.run(*cmd)
+
fname = os.path.join(tmpdir, bintool_path)
if not os.path.exists(fname):
print(f"- File '{fname}' was not produced")
diff --git a/tools/binman/btool/mkeficapsule.py b/tools/binman/btool/mkeficapsule.py
new file mode 100644
index 00000000000..61179747ffa
--- /dev/null
+++ b/tools/binman/btool/mkeficapsule.py
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2023 Linaro Limited
+#
+"""Bintool implementation for mkeficapsule tool
+
+mkeficapsule is a tool used for generating EFI capsules.
+
+The following are the commandline options to be provided
+to the tool
+Usage: mkeficapsule [options] <image blob> <output file>
+Options:
+ -g, --guid <guid string> guid for image blob type
+ -i, --index <index> update image index
+ -I, --instance <instance> update hardware instance
+ -v, --fw-version <version> firmware version
+ -p, --private-key <privkey file> private key file
+ -c, --certificate <cert file> signer's certificate file
+ -m, --monotonic-count <count> monotonic count
+ -d, --dump_sig dump signature (*.p7)
+ -A, --fw-accept firmware accept capsule, requires GUID, no image blob
+ -R, --fw-revert firmware revert capsule, takes no GUID, no image blob
+ -o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff
+ -h, --help print a help message
+"""
+
+from binman import bintool
+
+class Bintoolmkeficapsule(bintool.Bintool):
+ """Handles the 'mkeficapsule' tool
+
+ This bintool is used for generating the EFI capsules. The
+ capsule generation parameters can either be specified through
+ commandline, or through a config file.
+ """
+ def __init__(self, name):
+ super().__init__(name, 'mkeficapsule tool for generating capsules')
+
+ def generate_capsule(self, image_index, image_guid, hardware_instance,
+ payload, output_fname, priv_key, pub_key,
+ monotonic_count=0, version=0, oemflags=0):
+ """Generate a capsule through commandline-provided parameters
+
+ Args:
+ image_index (int): Unique number for identifying payload image
+ image_guid (str): GUID used for identifying the image
+ hardware_instance (int): Optional unique hardware instance of
+ a device in the system. 0 if not being used
+ payload (str): Path to the input payload image
+ output_fname (str): Path to the output capsule file
+ priv_key (str): Path to the private key
+ pub_key(str): Path to the public key
+ monotonic_count (int): Count used when signing an image
+ version (int): Image version (Optional)
+ oemflags (int): Optional 16 bit OEM flags
+
+ Returns:
+ str: Tool output
+ """
+ args = [
+ f'--index={image_index}',
+ f'--guid={image_guid}',
+ f'--instance={hardware_instance}'
+ ]
+
+ if version:
+ args += [f'--fw-version={version}']
+ if oemflags:
+ args += [f'--capoemflag={oemflags}']
+ if priv_key and pub_key:
+ args += [
+ f'--monotonic-count={monotonic_count}',
+ f'--private-key={priv_key}',
+ f'--certificate={pub_key}'
+ ]
+
+ args += [
+ payload,
+ output_fname
+ ]
+
+ return self.run_cmd(*args)
+
+ def fetch(self, method):
+ """Fetch handler for mkeficapsule
+
+ This builds the tool from source
+
+ Returns:
+ tuple:
+ str: Filename of fetched file to copy to a suitable directory
+ str: Name of temp directory to remove, or None
+ """
+ if method != bintool.FETCH_BUILD:
+ return None
+
+ cmd = ['tools-only_defconfig', 'tools']
+ result = self.build_from_git(
+ 'https://source.denx.de/u-boot/u-boot.git',
+ cmd,
+ 'tools/mkeficapsule')
+ return result
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index e7dfe6b2a36..801bd946742 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -468,6 +468,70 @@ updating the EC on startup via software sync.
+.. _etype_efi_capsule:
+
+Entry: capsule: Entry for generating EFI Capsule files
+------------------------------------------------------
+
+The parameters needed for generation of the capsules can be provided
+as properties in the entry.
+
+Properties / Entry arguments:
+ - image-index: Unique number for identifying corresponding
+ payload image. Number between 1 and descriptor count, i.e.
+ the total number of firmware images that can be updated. Mandatory
+ property.
+ - image-guid: Image GUID which will be used for identifying the
+ updatable image on the board. Mandatory property.
+ - hardware-instance: Optional number for identifying unique
+ hardware instance of a device in the system. Default value of 0
+ for images where value is not to be used.
+ - fw-version: Value of image version that can be put on the capsule
+ through the Firmware Management Protocol(FMP) header.
+ - monotonic-count: Count used when signing an image.
+ - private-key: Path to PEM formatted .key private key file. Mandatory
+ property for generating signed capsules.
+ - public-key-cert: Path to PEM formatted .crt public key certificate
+ file. Mandatory property for generating signed capsules.
+ - oem-flags - OEM flags to be passed through capsule header.
+
+ Since this is a subclass of Entry_section, all properties of the parent
+ class also apply here. Except for the properties stated as mandatory, the
+ rest of the properties are optional.
+
+For more details on the description of the capsule format, and the capsule
+update functionality, refer Section 8.5 and Chapter 23 in the `UEFI
+specification`_.
+
+The capsule parameters like image index and image GUID are passed as
+properties in the entry. The payload to be used in the capsule is to be
+provided as a subnode of the capsule entry.
+
+A typical capsule entry node would then look something like this::
+
+ capsule {
+ type = "efi-capsule";
+ image-index = <0x1>;
+ /* Image GUID for testing capsule update */
+ image-guid = SANDBOX_UBOOT_IMAGE_GUID;
+ hardware-instance = <0x0>;
+ private-key = "path/to/the/private/key";
+ public-key-cert = "path/to/the/public-key-cert";
+ oem-flags = <0x8000>;
+
+ u-boot {
+ };
+ };
+
+In the above example, the capsule payload is the U-Boot image. The
+capsule entry would read the contents of the payload and put them
+into the capsule. Any external file can also be specified as the
+payload using the blob-ext subnode.
+
+.. _`UEFI specification`: https://uefi.org/sites/default/files/resources/UEFI_Spec_2_10_Aug29.pdf
+
+
+
.. _etype_encrypted:
Entry: encrypted: Externally built encrypted binary blob
diff --git a/tools/binman/etype/efi_capsule.py b/tools/binman/etype/efi_capsule.py
new file mode 100644
index 00000000000..006eb630adb
--- /dev/null
+++ b/tools/binman/etype/efi_capsule.py
@@ -0,0 +1,143 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2023 Linaro Limited
+#
+# Entry-type module for producing a EFI capsule
+#
+
+import os
+
+from binman.entry import Entry
+from binman.etype.section import Entry_section
+from dtoc import fdt_util
+from u_boot_pylib import tools
+
+class Entry_efi_capsule(Entry_section):
+ """Generate EFI capsules
+
+ The parameters needed for generation of the capsules can
+ be provided as properties in the entry.
+
+ Properties / Entry arguments:
+ - image-index: Unique number for identifying corresponding
+ payload image. Number between 1 and descriptor count, i.e.
+ the total number of firmware images that can be updated. Mandatory
+ property.
+ - image-guid: Image GUID which will be used for identifying the
+ updatable image on the board. Mandatory property.
+ - hardware-instance: Optional number for identifying unique
+ hardware instance of a device in the system. Default value of 0
+ for images where value is not to be used.
+ - fw-version: Value of image version that can be put on the capsule
+ through the Firmware Management Protocol(FMP) header.
+ - monotonic-count: Count used when signing an image.
+ - private-key: Path to PEM formatted .key private key file. Mandatory
+ property for generating signed capsules.
+ - public-key-cert: Path to PEM formatted .crt public key certificate
+ file. Mandatory property for generating signed capsules.
+ - oem-flags - OEM flags to be passed through capsule header.
+
+ Since this is a subclass of Entry_section, all properties of the parent
+ class also apply here. Except for the properties stated as mandatory, the
+ rest of the properties are optional.
+
+ For more details on the description of the capsule format, and the capsule
+ update functionality, refer Section 8.5 and Chapter 23 in the `UEFI
+ specification`_.
+
+ The capsule parameters like image index and image GUID are passed as
+ properties in the entry. The payload to be used in the capsule is to be
+ provided as a subnode of the capsule entry.
+
+ A typical capsule entry node would then look something like this
+
+ capsule {
+ type = "efi-capsule";
+ image-index = <0x1>;
+ /* Image GUID for testing capsule update */
+ image-guid = SANDBOX_UBOOT_IMAGE_GUID;
+ hardware-instance = <0x0>;
+ private-key = "path/to/the/private/key";
+ public-key-cert = "path/to/the/public-key-cert";
+ oem-flags = <0x8000>;
+
+ u-boot {
+ };
+ };
+
+ In the above example, the capsule payload is the U-Boot image. The
+ capsule entry would read the contents of the payload and put them
+ into the capsule. Any external file can also be specified as the
+ payload using the blob-ext subnode.
+
+ .. _`UEFI specification`: https://uefi.org/sites/default/files/resources/UEFI_Spec_2_10_Aug29.pdf
+ """
+ def __init__(self, section, etype, node):
+ super().__init__(section, etype, node)
+ self.required_props = ['image-index', 'image-guid']
+ self.image_index = 0
+ self.image_guid = ''
+ self.hardware_instance = 0
+ self.monotonic_count = 0
+ self.fw_version = 0
+ self.oem_flags = 0
+ self.private_key = ''
+ self.public_key_cert = ''
+ self.auth = 0
+
+ def ReadNode(self):
+ super().ReadNode()
+
+ self.image_index = fdt_util.GetInt(self._node, 'image-index')
+ self.image_guid = fdt_util.GetString(self._node, 'image-guid')
+ self.fw_version = fdt_util.GetInt(self._node, 'fw-version')
+ self.hardware_instance = fdt_util.GetInt(self._node, 'hardware-instance')
+ self.monotonic_count = fdt_util.GetInt(self._node, 'monotonic-count')
+ self.oem_flags = fdt_util.GetInt(self._node, 'oem-flags')
+
+ self.private_key = fdt_util.GetString(self._node, 'private-key')
+ self.public_key_cert = fdt_util.GetString(self._node, 'public-key-cert')
+ if ((self.private_key and not self.public_key_cert) or (self.public_key_cert and not self.private_key)):
+ self.Raise('Both private key and public key certificate need to be provided')
+ elif not (self.private_key and self.public_key_cert):
+ self.auth = 0
+ else:
+ self.auth = 1
+
+ def BuildSectionData(self, required):
+ def get_binman_test_guid(type_str):
+ TYPE_TO_GUID = {
+ 'binman-test' : '09d7cf52-0720-4710-91d1-08469b7fe9c8'
+ }
+ return TYPE_TO_GUID[type_str]
+
+ private_key = ''
+ public_key_cert = ''
+ if self.auth:
+ if not os.path.isabs(self.private_key):
+ private_key = tools.get_input_filename(self.private_key)
+ if not os.path.isabs(self.public_key_cert):
+ public_key_cert = tools.get_input_filename(self.public_key_cert)
+ data, payload, uniq = self.collect_contents_to_file(
+ self._entries.values(), 'capsule_in')
+ outfile = self._filename if self._filename else 'capsule.%s' % uniq
+ capsule_fname = tools.get_output_filename(outfile)
+ guid = self.image_guid
+ if self.image_guid == "binman-test":
+ guid = get_binman_test_guid('binman-test')
+
+ ret = self.mkeficapsule.generate_capsule(self.image_index,
+ guid,
+ self.hardware_instance,
+ payload,
+ capsule_fname,
+ private_key,
+ public_key_cert,
+ self.monotonic_count,
+ self.fw_version,
+ self.oem_flags)
+ if ret is not None:
+ os.remove(payload)
+ return tools.read_file(capsule_fname)
+
+ def AddBintools(self, btools):
+ self.mkeficapsule = self.AddBintool(btools, 'mkeficapsule')
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 1293e9dbf42..8e419645a6d 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -48,6 +48,7 @@ U_BOOT_VPL_DATA = b'vpl76543210fedcbazywxyz_'
BLOB_DATA = b'89'
ME_DATA = b'0abcd'
VGA_DATA = b'vga'
+EFI_CAPSULE_DATA = b'efi'
U_BOOT_DTB_DATA = b'udtb'
U_BOOT_SPL_DTB_DATA = b'spldtb'
U_BOOT_TPL_DTB_DATA = b'tpldtb'
@@ -119,6 +120,11 @@ COMP_BINTOOLS = ['bzip2', 'gzip', 'lz4', 'lzma_alone', 'lzop', 'xz', 'zstd']
TEE_ADDR = 0x5678
+# Firmware Management Protocol(FMP) GUID
+FW_MGMT_GUID = 'edd5cb6d2de8444cbda17194199ad92a'
+# Image GUID specified in the DTS
+CAPSULE_IMAGE_GUID = '52cfd7092007104791d108469b7fe9c8'
+
class TestFunctional(unittest.TestCase):
"""Functional tests for binman
@@ -215,6 +221,7 @@ class TestFunctional(unittest.TestCase):
TestFunctional._MakeInputFile('scp.bin', SCP_DATA)
TestFunctional._MakeInputFile('rockchip-tpl.bin', ROCKCHIP_TPL_DATA)
TestFunctional._MakeInputFile('ti_unsecure.bin', TI_UNSECURE_DATA)
+ TestFunctional._MakeInputFile('capsule_input.bin', EFI_CAPSULE_DATA)
# Add a few .dtb files for testing
TestFunctional._MakeInputFile('%s/test-fdt1.dtb' % TEST_FDT_SUBDIR,
@@ -7216,5 +7223,116 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
self.assertRegex(err,
"Image 'image'.*missing bintools.*: bootgen")
+ def _CheckCapsule(self, data, signed_capsule=False, version_check=False,
+ capoemflags=False):
+ fmp_signature = "4d535331" # 'M', 'S', 'S', '1'
+ fmp_size = "10"
+ fmp_fw_version = "02"
+ oemflag = "0080"
+
+ payload_data = EFI_CAPSULE_DATA
+
+ # TODO - Currently, these offsets for capsule fields are hardcoded.
+ # There are plans to add support to the mkeficapsule tool to dump
+ # the capsule contents which can then be used for capsule
+ # verification.
+
+ # Firmware Management Protocol(FMP) GUID - offset(0 - 32)
+ self.assertEqual(FW_MGMT_GUID, data.hex()[:32])
+ # Image GUID - offset(96 - 128)
+ self.assertEqual(CAPSULE_IMAGE_GUID, data.hex()[96:128])
+
+ if capoemflags:
+ # OEM Flags - offset(40 - 44)
+ self.assertEqual(oemflag, data.hex()[40:44])
+ if signed_capsule and version_check:
+ # FMP header signature - offset(4770 - 4778)
+ self.assertEqual(fmp_signature, data.hex()[4770:4778])
+ # FMP header size - offset(4778 - 4780)
+ self.assertEqual(fmp_size, data.hex()[4778:4780])
+ # firmware version - offset(4786 - 4788)
+ self.assertEqual(fmp_fw_version, data.hex()[4786:4788])
+ # payload offset signed capsule(4802 - 4808)
+ self.assertEqual(payload_data.hex(), data.hex()[4802:4808])
+ elif signed_capsule:
+ # payload offset signed capsule(4770 - 4776)
+ self.assertEqual(payload_data.hex(), data.hex()[4770:4776])
+ elif version_check:
+ # FMP header signature - offset(184 - 192)
+ self.assertEqual(fmp_signature, data.hex()[184:192])
+ # FMP header size - offset(192 - 194)
+ self.assertEqual(fmp_size, data.hex()[192:194])
+ # firmware version - offset(200 - 202)
+ self.assertEqual(fmp_fw_version, data.hex()[200:202])
+ # payload offset for non-signed capsule with version header(216 - 222)
+ self.assertEqual(payload_data.hex(), data.hex()[216:222])
+ else:
+ # payload offset for non-signed capsule with no version header(184 - 190)
+ self.assertEqual(payload_data.hex(), data.hex()[184:190])
+
+ def testCapsuleGen(self):
+ """Test generation of EFI capsule"""
+ data = self._DoReadFile('311_capsule.dts')
+
+ self._CheckCapsule(data)
+
+ def testSignedCapsuleGen(self):
+ """Test generation of EFI capsule"""
+ data = tools.read_file(self.TestFile("key.key"))
+ self._MakeInputFile("key.key", data)
+ data = tools.read_file(self.TestFile("key.pem"))
+ self._MakeInputFile("key.crt", data)
+
+ data = self._DoReadFile('312_capsule_signed.dts')
+
+ self._CheckCapsule(data, signed_capsule=True)
+
+ def testCapsuleGenVersionSupport(self):
+ """Test generation of EFI capsule with version support"""
+ data = self._DoReadFile('313_capsule_version.dts')
+
+ self._CheckCapsule(data, version_check=True)
+
+ def testCapsuleGenSignedVer(self):
+ """Test generation of signed EFI capsule with version information"""
+ data = tools.read_file(self.TestFile("key.key"))
+ self._MakeInputFile("key.key", data)
+ data = tools.read_file(self.TestFile("key.pem"))
+ self._MakeInputFile("key.crt", data)
+
+ data = self._DoReadFile('314_capsule_signed_ver.dts')
+
+ self._CheckCapsule(data, signed_capsule=True, version_check=True)
+
+ def testCapsuleGenCapOemFlags(self):
+ """Test generation of EFI capsule with OEM Flags set"""
+ data = self._DoReadFile('315_capsule_oemflags.dts')
+
+ self._CheckCapsule(data, capoemflags=True)
+
+ def testCapsuleGenKeyMissing(self):
+ """Test that binman errors out on missing key"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFile('316_capsule_missing_key.dts')
+
+ self.assertIn("Both private key and public key certificate need to be provided",
+ str(e.exception))
+
+ def testCapsuleGenIndexMissing(self):
+ """Test that binman errors out on missing image index"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFile('317_capsule_missing_index.dts')
+
+ self.assertIn("entry is missing properties: image-index",
+ str(e.exception))
+
+ def testCapsuleGenGuidMissing(self):
+ """Test that binman errors out on missing image GUID"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFile('318_capsule_missing_guid.dts')
+
+ self.assertIn("entry is missing properties: image-guid",
+ str(e.exception))
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/test/311_capsule.dts b/tools/binman/test/311_capsule.dts
new file mode 100644
index 00000000000..8eb4250b14b
--- /dev/null
+++ b/tools/binman/test/311_capsule.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ efi-capsule {
+ image-index = <0x1>;
+ /* Image GUID for testing capsule update */
+ image-guid = "binman-test";
+ hardware-instance = <0x0>;
+
+ blob {
+ filename = "capsule_input.bin";
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/312_capsule_signed.dts b/tools/binman/test/312_capsule_signed.dts
new file mode 100644
index 00000000000..d1c76e269c7
--- /dev/null
+++ b/tools/binman/test/312_capsule_signed.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ efi-capsule {
+ image-index = <0x1>;
+ /* Image GUID for testing capsule update */
+ image-guid = "binman-test";
+ hardware-instance = <0x0>;
+ private-key = "key.key";
+ public-key-cert = "key.crt";
+
+ blob {
+ filename = "capsule_input.bin";
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/313_capsule_version.dts b/tools/binman/test/313_capsule_version.dts
new file mode 100644
index 00000000000..bafef3609e0
--- /dev/null
+++ b/tools/binman/test/313_capsule_version.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ efi-capsule {
+ image-index = <0x1>;
+ fw-version = <0x2>;
+ /* Image GUID for testing capsule update */
+ image-guid = "binman-test";
+ hardware-instance = <0x0>;
+
+ blob {
+ filename = "capsule_input.bin";
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/314_capsule_signed_ver.dts b/tools/binman/test/314_capsule_signed_ver.dts
new file mode 100644
index 00000000000..85c784bba43
--- /dev/null
+++ b/tools/binman/test/314_capsule_signed_ver.dts
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ efi-capsule {
+ image-index = <0x1>;
+ fw-version = <0x2>;
+ /* Image GUID for testing capsule update */
+ image-guid = "binman-test";
+ hardware-instance = <0x0>;
+ private-key = "key.key";
+ public-key-cert = "key.crt";
+
+ blob {
+ filename = "capsule_input.bin";
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/315_capsule_oemflags.dts b/tools/binman/test/315_capsule_oemflags.dts
new file mode 100644
index 00000000000..f736e8758fd
--- /dev/null
+++ b/tools/binman/test/315_capsule_oemflags.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ efi-capsule {
+ image-index = <0x1>;
+ /* Image GUID for testing capsule update */
+ image-guid = "binman-test";
+ hardware-instance = <0x0>;
+ oem-flags = <0x8000>;
+
+ blob {
+ filename = "capsule_input.bin";
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/316_capsule_missing_key.dts b/tools/binman/test/316_capsule_missing_key.dts
new file mode 100644
index 00000000000..2080b50e3dd
--- /dev/null
+++ b/tools/binman/test/316_capsule_missing_key.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ efi-capsule {
+ image-index = <0x1>;
+ /* Image GUID for testing capsule update */
+ image-guid = "binman-test";
+ hardware-instance = <0x0>;
+ private-key = "tools/binman/test/key.key";
+
+ blob {
+ filename = "capsule_input.bin";
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/317_capsule_missing_index.dts b/tools/binman/test/317_capsule_missing_index.dts
new file mode 100644
index 00000000000..aadb61f6477
--- /dev/null
+++ b/tools/binman/test/317_capsule_missing_index.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ efi-capsule {
+ /* Image GUID for testing capsule update */
+ image-guid = "binman-test";
+ hardware-instance = <0x0>;
+
+ blob {
+ filename = "capsule_input.bin";
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/318_capsule_missing_guid.dts b/tools/binman/test/318_capsule_missing_guid.dts
new file mode 100644
index 00000000000..d76afba853e
--- /dev/null
+++ b/tools/binman/test/318_capsule_missing_guid.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ efi-capsule {
+ image-index = <0x1>;
+ hardware-instance = <0x0>;
+
+ blob {
+ filename = "capsule_input.bin";
+ };
+ };
+ };
+};