From: AKASHI Takahiro <takahiro.akashi@linaro.org>
To: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: agraf@csgraf.de, sjg@chromium.org, ilias.apalodimas@linaro.org,
sughosh.ganu@linaro.org, masami.hiramatsu@linaro.org,
mark.kettenis@xs4all.nl, u-boot@lists.denx.de
Subject: Re: [PATCH v8 06/12] test/py: efi_capsule: add image authentication test
Date: Mon, 17 Jan 2022 11:03:55 +0900 [thread overview]
Message-ID: <20220117020355.GD7045@laputa> (raw)
In-Reply-To: <93ac022e-ed13-7acd-40a2-783a9188d071@gmx.de>
On Sat, Jan 01, 2022 at 11:18:47PM +0100, Heinrich Schuchardt wrote:
> On 12/20/21 06:02, AKASHI Takahiro wrote:
> > Add a couple of test cases against capsule image authentication
> > for capsule-on-disk, where only a signed capsule file with the verified
> > signature will be applied to the system.
> >
> > Due to the difficulty of embedding a public key (esl file) in U-Boot
> > binary during pytest setup time, all the keys/certificates are pre-created.
> >
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > Reviewed-by: Simon Glass <sjg@chromium.org>
> > Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > ---
> > .../py/tests/test_efi_capsule/capsule_defs.py | 5 +
> > test/py/tests/test_efi_capsule/conftest.py | 52 +++-
> > test/py/tests/test_efi_capsule/signature.dts | 10 +
> > .../test_capsule_firmware_signed.py | 254 ++++++++++++++++++
> > 4 files changed, 318 insertions(+), 3 deletions(-)
> > create mode 100644 test/py/tests/test_efi_capsule/signature.dts
> > create mode 100644 test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
> >
> > diff --git a/test/py/tests/test_efi_capsule/capsule_defs.py b/test/py/tests/test_efi_capsule/capsule_defs.py
> > index 4fd6353c2040..aa9bf5eee3aa 100644
> > --- a/test/py/tests/test_efi_capsule/capsule_defs.py
> > +++ b/test/py/tests/test_efi_capsule/capsule_defs.py
> > @@ -3,3 +3,8 @@
> > # Directories
> > CAPSULE_DATA_DIR = '/EFI/CapsuleTestData'
> > CAPSULE_INSTALL_DIR = '/EFI/UpdateCapsule'
> > +
> > +# v1.5.1 or earlier of efitools has a bug in sha256 calculation, and
> > +# you need build a newer version on your own.
>
> Why should I build it on my own? The version in Debian Bullseye and
> Ubuntu Impish is 1.9.2. Is your Linux distro outdated?
?
This is just a cautious warning for users who might hit this bug
in their own environment.
> > +# The path must terminate with '/'.
> > +EFITOOLS_PATH = ''
>
> This is contradictory.
> '' seems not to be '/' terminated.
OK. I will describe it more specifically, adding "if the path is not NULL".
> > diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py
> > index 6ad5608cd71c..27c05971ca32 100644
> > --- a/test/py/tests/test_efi_capsule/conftest.py
> > +++ b/test/py/tests/test_efi_capsule/conftest.py
> > @@ -10,13 +10,13 @@ import pytest
> > from capsule_defs import *
> >
> > #
> > -# Fixture for UEFI secure boot test
> > +# Fixture for UEFI capsule test
> > #
> >
> > -
> > @pytest.fixture(scope='session')
> > def efi_capsule_data(request, u_boot_config):
> > - """Set up a file system to be used in UEFI capsule test.
> > + """Set up a file system to be used in UEFI capsule and
> > + authentication test.
> >
> > Args:
> > request: Pytest request object.
> > @@ -40,6 +40,36 @@ def efi_capsule_data(request, u_boot_config):
> > check_call('mkdir -p %s' % data_dir, shell=True)
> > check_call('mkdir -p %s' % install_dir, shell=True)
> >
> > + capsule_auth_enabled = u_boot_config.buildconfig.get(
> > + 'config_efi_capsule_authenticate')
> > + 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)
> > +
> > + # Create *malicious* private key (SIGNER2.key) and certificate
>
> There is nothing malicious in an unsupported private key.
>
> %s/\*malicious\*/unsupported/
I believe that "unsupported" is very much ambiguous and
"malicious" is much better in terms of the test purpose
in this test case.
For instance, the key should be invalidated if it was broken
or the image was signed by a faked or "malicious" key.
-Takahiro Akashi
> Best regards
>
> Heinrich
>
> > + # (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)
> > +
> > # 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,
> > @@ -56,6 +86,22 @@ def efi_capsule_data(request, u_boot_config):
> > check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --index 1 Test02' %
> > (data_dir, u_boot_config.build_dir),
> > shell=True)
> > + if capsule_auth_enabled:
> > + # firmware signed with proper key
> > + check_call('cd %s; '
> > + '%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
> > + '--private-key SIGNER.key --certificate SIGNER.crt '
> > + '--raw u-boot.bin.new Test11'
> > + % (data_dir, u_boot_config.build_dir),
> > + shell=True)
> > + # firmware signed with *mal* key
> > + check_call('cd %s; '
> > + '%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
> > + '--private-key SIGNER2.key '
> > + '--certificate SIGNER2.crt '
> > + '--raw u-boot.bin.new Test12'
> > + % (data_dir, u_boot_config.build_dir),
> > + shell=True)
> >
> > # 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
> > new file mode 100644
> > index 000000000000..078cfc76c93c
> > --- /dev/null
> > +++ b/test/py/tests/test_efi_capsule/signature.dts
> > @@ -0,0 +1,10 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +
> > +/dts-v1/;
> > +/plugin/;
> > +
> > +&{/} {
> > + signature {
> > + capsule-key = /incbin/("SIGNER.esl");
> > + };
> > +};
> > diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py b/test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
> > new file mode 100644
> > index 000000000000..593b032e9015
> > --- /dev/null
> > +++ b/test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
> > @@ -0,0 +1,254 @@
> > +# SPDX-License-Identifier: GPL-2.0+
> > +# Copyright (c) 2021, Linaro Limited
> > +# Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > +#
> > +# U-Boot UEFI: Firmware Update (Signed capsule) Test
> > +
> > +"""
> > +This test verifies capsule-on-disk firmware update
> > +with signed capsule files
> > +"""
> > +
> > +import pytest
> > +from capsule_defs import CAPSULE_DATA_DIR, CAPSULE_INSTALL_DIR
> > +
> > +@pytest.mark.boardspec('sandbox')
> > +@pytest.mark.buildconfigspec('efi_capsule_firmware_raw')
> > +@pytest.mark.buildconfigspec('efi_capsule_authenticate')
> > +@pytest.mark.buildconfigspec('dfu')
> > +@pytest.mark.buildconfigspec('dfu_sf')
> > +@pytest.mark.buildconfigspec('cmd_efidebug')
> > +@pytest.mark.buildconfigspec('cmd_fat')
> > +@pytest.mark.buildconfigspec('cmd_memory')
> > +@pytest.mark.buildconfigspec('cmd_nvedit_efi')
> > +@pytest.mark.buildconfigspec('cmd_sf')
> > +@pytest.mark.slow
> > +class TestEfiCapsuleFirmwareSigned(object):
> > + def test_efi_capsule_auth1(
> > + self, u_boot_config, u_boot_console, efi_capsule_data):
> > + """
> > + Test Case 1 - Update U-Boot on SPI Flash, raw image format
> > + 0x100000-0x150000: U-Boot binary (but dummy)
> > +
> > + If the capsule is properly signed, the authentication
> > + should pass and the firmware be updated.
> > + """
> > + disk_img = efi_capsule_data
> > + with u_boot_console.log.section('Test Case 1-a, before reboot'):
> > + output = u_boot_console.run_command_list([
> > + 'host bind 0 %s' % disk_img,
> > + 'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi',
> > + 'efidebug boot order 1',
> > + 'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
> > + 'env set dfu_alt_info '
> > + '"sf 0:0=u-boot-bin raw 0x100000 '
> > + '0x50000;u-boot-env raw 0x150000 0x200000"',
> > + 'env save'])
> > +
> > + # initialize content
> > + output = u_boot_console.run_command_list([
> > + 'sf probe 0:0',
> > + 'fatload host 0:1 4000000 %s/u-boot.bin.old'
> > + % CAPSULE_DATA_DIR,
> > + 'sf write 4000000 100000 10',
> > + 'sf read 5000000 100000 10',
> > + 'md.b 5000000 10'])
> > + assert 'Old' in ''.join(output)
> > +
> > + # place a capsule file
> > + output = u_boot_console.run_command_list([
> > + 'fatload host 0:1 4000000 %s/Test11' % CAPSULE_DATA_DIR,
> > + 'fatwrite host 0:1 4000000 %s/Test11 $filesize'
> > + % CAPSULE_INSTALL_DIR,
> > + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > + assert 'Test11' in ''.join(output)
> > +
> > + # reboot
> > + mnt_point = u_boot_config.persistent_data_dir + '/test_efi_capsule'
> > + u_boot_console.config.dtb = mnt_point + CAPSULE_DATA_DIR \
> > + + '/test_sig.dtb'
> > + u_boot_console.restart_uboot()
> > +
> > + capsule_early = u_boot_config.buildconfig.get(
> > + 'config_efi_capsule_on_disk_early')
> > + with u_boot_console.log.section('Test Case 1-b, after reboot'):
> > + if not capsule_early:
> > + # make sure that dfu_alt_info exists even persistent variables
> > + # are not available.
> > + output = u_boot_console.run_command_list([
> > + 'env set dfu_alt_info '
> > + '"sf 0:0=u-boot-bin raw 0x100000 '
> > + '0x50000;u-boot-env raw 0x150000 0x200000"',
> > + 'host bind 0 %s' % disk_img,
> > + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > + assert 'Test11' in ''.join(output)
> > +
> > + # need to run uefi command to initiate capsule handling
> > + output = u_boot_console.run_command(
> > + 'env print -e Capsule0000')
> > +
> > + output = u_boot_console.run_command_list([
> > + 'host bind 0 %s' % disk_img,
> > + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > + assert 'Test11' not in ''.join(output)
> > +
> > + output = u_boot_console.run_command_list([
> > + 'sf probe 0:0',
> > + 'sf read 4000000 100000 10',
> > + 'md.b 4000000 10'])
> > + assert 'u-boot:New' in ''.join(output)
> > +
> > + def test_efi_capsule_auth2(
> > + self, u_boot_config, u_boot_console, efi_capsule_data):
> > + """
> > + Test Case 2 - Update U-Boot on SPI Flash, raw image format
> > + 0x100000-0x150000: U-Boot binary (but dummy)
> > +
> > + If the capsule is signed but with an invalid key,
> > + the authentication should fail and the firmware
> > + not be updated.
> > + """
> > + disk_img = efi_capsule_data
> > + with u_boot_console.log.section('Test Case 2-a, before reboot'):
> > + output = u_boot_console.run_command_list([
> > + 'host bind 0 %s' % disk_img,
> > + 'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi',
> > + 'efidebug boot order 1',
> > + 'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
> > + 'env set dfu_alt_info '
> > + '"sf 0:0=u-boot-bin raw 0x100000 '
> > + '0x50000;u-boot-env raw 0x150000 0x200000"',
> > + 'env save'])
> > +
> > + # initialize content
> > + output = u_boot_console.run_command_list([
> > + 'sf probe 0:0',
> > + 'fatload host 0:1 4000000 %s/u-boot.bin.old'
> > + % CAPSULE_DATA_DIR,
> > + 'sf write 4000000 100000 10',
> > + 'sf read 5000000 100000 10',
> > + 'md.b 5000000 10'])
> > + assert 'Old' in ''.join(output)
> > +
> > + # place a capsule file
> > + output = u_boot_console.run_command_list([
> > + 'fatload host 0:1 4000000 %s/Test12' % CAPSULE_DATA_DIR,
> > + 'fatwrite host 0:1 4000000 %s/Test12 $filesize'
> > + % CAPSULE_INSTALL_DIR,
> > + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > + assert 'Test12' in ''.join(output)
> > +
> > + # reboot
> > + mnt_point = u_boot_config.persistent_data_dir + '/test_efi_capsule'
> > + u_boot_console.config.dtb = mnt_point + CAPSULE_DATA_DIR \
> > + + '/test_sig.dtb'
> > + u_boot_console.restart_uboot()
> > +
> > + capsule_early = u_boot_config.buildconfig.get(
> > + 'config_efi_capsule_on_disk_early')
> > + with u_boot_console.log.section('Test Case 2-b, after reboot'):
> > + if not capsule_early:
> > + # make sure that dfu_alt_info exists even persistent variables
> > + # are not available.
> > + output = u_boot_console.run_command_list([
> > + 'env set dfu_alt_info '
> > + '"sf 0:0=u-boot-bin raw 0x100000 '
> > + '0x50000;u-boot-env raw 0x150000 0x200000"',
> > + 'host bind 0 %s' % disk_img,
> > + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > + assert 'Test12' in ''.join(output)
> > +
> > + # need to run uefi command to initiate capsule handling
> > + output = u_boot_console.run_command(
> > + 'env print -e Capsule0000')
> > +
> > + # deleted any way
> > + output = u_boot_console.run_command_list([
> > + 'host bind 0 %s' % disk_img,
> > + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > + assert 'Test12' not in ''.join(output)
> > +
> > + # TODO: check CapsuleStatus in CapsuleXXXX
> > +
> > + output = u_boot_console.run_command_list([
> > + 'sf probe 0:0',
> > + 'sf read 4000000 100000 10',
> > + 'md.b 4000000 10'])
> > + assert 'u-boot:Old' in ''.join(output)
> > +
> > + def test_efi_capsule_auth3(
> > + self, u_boot_config, u_boot_console, efi_capsule_data):
> > + """
> > + Test Case 3 - Update U-Boot on SPI Flash, raw image format
> > + 0x100000-0x150000: U-Boot binary (but dummy)
> > +
> > + If the capsule is not signed, the authentication
> > + should fail and the firmware not be updated.
> > + """
> > + disk_img = efi_capsule_data
> > + with u_boot_console.log.section('Test Case 3-a, before reboot'):
> > + output = u_boot_console.run_command_list([
> > + 'host bind 0 %s' % disk_img,
> > + 'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi',
> > + 'efidebug boot order 1',
> > + 'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
> > + 'env set dfu_alt_info '
> > + '"sf 0:0=u-boot-bin raw 0x100000 '
> > + '0x50000;u-boot-env raw 0x150000 0x200000"',
> > + 'env save'])
> > +
> > + # initialize content
> > + output = u_boot_console.run_command_list([
> > + 'sf probe 0:0',
> > + 'fatload host 0:1 4000000 %s/u-boot.bin.old'
> > + % CAPSULE_DATA_DIR,
> > + 'sf write 4000000 100000 10',
> > + 'sf read 5000000 100000 10',
> > + 'md.b 5000000 10'])
> > + assert 'Old' in ''.join(output)
> > +
> > + # place a capsule file
> > + output = u_boot_console.run_command_list([
> > + 'fatload host 0:1 4000000 %s/Test02' % CAPSULE_DATA_DIR,
> > + 'fatwrite host 0:1 4000000 %s/Test02 $filesize'
> > + % CAPSULE_INSTALL_DIR,
> > + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > + assert 'Test02' in ''.join(output)
> > +
> > + # reboot
> > + mnt_point = u_boot_config.persistent_data_dir + '/test_efi_capsule'
> > + u_boot_console.config.dtb = mnt_point + CAPSULE_DATA_DIR \
> > + + '/test_sig.dtb'
> > + u_boot_console.restart_uboot()
> > +
> > + capsule_early = u_boot_config.buildconfig.get(
> > + 'config_efi_capsule_on_disk_early')
> > + with u_boot_console.log.section('Test Case 3-b, after reboot'):
> > + if not capsule_early:
> > + # make sure that dfu_alt_info exists even persistent variables
> > + # are not available.
> > + output = u_boot_console.run_command_list([
> > + 'env set dfu_alt_info '
> > + '"sf 0:0=u-boot-bin raw 0x100000 '
> > + '0x50000;u-boot-env raw 0x150000 0x200000"',
> > + 'host bind 0 %s' % disk_img,
> > + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > + assert 'Test02' in ''.join(output)
> > +
> > + # need to run uefi command to initiate capsule handling
> > + output = u_boot_console.run_command(
> > + 'env print -e Capsule0000')
> > +
> > + # deleted any way
> > + output = u_boot_console.run_command_list([
> > + 'host bind 0 %s' % disk_img,
> > + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > + assert 'Test02' not in ''.join(output)
> > +
> > + # TODO: check CapsuleStatus in CapsuleXXXX
> > +
> > + output = u_boot_console.run_command_list([
> > + 'sf probe 0:0',
> > + 'sf read 4000000 100000 10',
> > + 'md.b 4000000 10'])
> > + assert 'u-boot:Old' in ''.join(output)
>
next prev parent reply other threads:[~2022-01-17 2:04 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-20 5:02 [PATCH v8 00/12] efi_loader: capsule: improve capsule authentication support AKASHI Takahiro
2021-12-20 5:02 ` [PATCH v8 01/12] tools: mkeficapsule: rework the code a little bit AKASHI Takahiro
2022-01-01 21:35 ` Heinrich Schuchardt
2022-01-06 9:01 ` AKASHI Takahiro
2021-12-20 5:02 ` [PATCH v8 02/12] tools: build mkeficapsule with tools-only_defconfig AKASHI Takahiro
2022-01-01 21:42 ` Heinrich Schuchardt
2022-01-06 9:20 ` AKASHI Takahiro
2022-01-12 20:03 ` Simon Glass
2021-12-20 5:02 ` [PATCH v8 03/12] tools: mkeficapsule: add firmwware image signing AKASHI Takahiro
2022-01-01 21:50 ` Heinrich Schuchardt
2022-01-17 8:11 ` AKASHI Takahiro
2021-12-20 5:02 ` [PATCH v8 04/12] tools: mkeficapsule: add man page AKASHI Takahiro
2022-01-01 22:02 ` Heinrich Schuchardt
2022-01-06 10:25 ` AKASHI Takahiro
2022-01-06 19:26 ` Heinrich Schuchardt
2022-01-07 2:31 ` AKASHI Takahiro
2022-01-09 22:40 ` Heinrich Schuchardt
2021-12-20 5:02 ` [PATCH v8 05/12] doc: update UEFI document for usage of mkeficapsule AKASHI Takahiro
2022-01-01 22:09 ` Heinrich Schuchardt
2022-01-07 2:20 ` AKASHI Takahiro
2022-01-09 22:36 ` Heinrich Schuchardt
2021-12-20 5:02 ` [PATCH v8 06/12] test/py: efi_capsule: add image authentication test AKASHI Takahiro
2022-01-01 22:18 ` Heinrich Schuchardt
2022-01-17 2:03 ` AKASHI Takahiro [this message]
2021-12-20 5:02 ` [PATCH v8 07/12] tools: mkeficapsule: allow for specifying GUID explicitly AKASHI Takahiro
2022-01-01 22:42 ` Heinrich Schuchardt
2022-01-17 2:14 ` AKASHI Takahiro
2021-12-20 5:02 ` [PATCH v8 08/12] test/py: efi_capsule: align with the syntax change of mkeficapsule AKASHI Takahiro
2021-12-20 5:02 ` [PATCH v8 09/12] test/py: efi_capsule: add a test for "--guid" option AKASHI Takahiro
2021-12-20 5:02 ` [PATCH v8 10/12] test/py: efi_capsule: check the results in case of CAPSULE_AUTHENTICATE AKASHI Takahiro
2021-12-20 5:02 ` [PATCH v8 11/12] (RFC) tools: add fdtsig.sh AKASHI Takahiro
2021-12-20 5:02 ` [PATCH v8 12/12] (RFC) efi_loader, dts: add public keys for capsules to device tree AKASHI Takahiro
2022-01-01 22:53 ` Heinrich Schuchardt
2022-01-12 20:03 ` Simon Glass
2022-01-17 1:42 ` AKASHI Takahiro
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220117020355.GD7045@laputa \
--to=takahiro.akashi@linaro.org \
--cc=agraf@csgraf.de \
--cc=ilias.apalodimas@linaro.org \
--cc=mark.kettenis@xs4all.nl \
--cc=masami.hiramatsu@linaro.org \
--cc=sjg@chromium.org \
--cc=sughosh.ganu@linaro.org \
--cc=u-boot@lists.denx.de \
--cc=xypron.glpk@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox