[PATCH 5.3 regression fix] efi-stub: Fix get_efi_config_table on mixed-mode setups

2019-08-07 Thread Hans de Goede
Fix get_efi_config_table using the wrong structs when booting a
64 bit kernel on 32 bit firmware.

Cc: Matthew Garrett 
Cc: Ard Biesheuvel 
Cc: Jarkko Sakkinen 
Fixes: 82d736ac56d7 ("Abstract out support for locating an EFI config table")
Signed-off-by: Hans de Goede 
---
 .../firmware/efi/libstub/efi-stub-helper.c| 38 +--
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c 
b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 1db780c0f07b..3caae7f2cf56 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -927,17 +927,33 @@ efi_status_t efi_exit_boot_services(efi_system_table_t 
*sys_table_arg,
return status;
 }
 
+#define GET_EFI_CONFIG_TABLE(bits) \
+static void *get_efi_config_table##bits(efi_system_table_t *_sys_table,
\
+   efi_guid_t guid)\
+{  \
+   efi_system_table_##bits##_t *sys_table; \
+   efi_config_table_##bits##_t *tables;\
+   int i;  \
+   \
+   sys_table = (typeof(sys_table))_sys_table;  \
+   tables = (typeof(tables))(unsigned long)sys_table->tables;  \
+   \
+   for (i = 0; i < sys_table->nr_tables; i++) {\
+   if (efi_guidcmp(tables[i].guid, guid) != 0) \
+   continue;   \
+   \
+   return (void *)(unsigned long)tables[i].table;  \
+   }   \
+   \
+   return NULL;\
+}
+GET_EFI_CONFIG_TABLE(32)
+GET_EFI_CONFIG_TABLE(64)
+
 void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid)
 {
-   efi_config_table_t *tables = (efi_config_table_t *)sys_table->tables;
-   int i;
-
-   for (i = 0; i < sys_table->nr_tables; i++) {
-   if (efi_guidcmp(tables[i].guid, guid) != 0)
-   continue;
-
-   return (void *)tables[i].table;
-   }
-
-   return NULL;
+   if (efi_is_64bit())
+   return get_efi_config_table64(sys_table, guid);
+   else
+   return get_efi_config_table32(sys_table, guid);
 }
-- 
2.22.0



Re: 5.3 boot regression caused by 5.3 TPM changes

2019-08-07 Thread Hans de Goede

Hi,

On 05-08-19 18:01, Ard Biesheuvel wrote:

On Sun, 4 Aug 2019 at 19:12, Hans de Goede  wrote:


Hi,

On 04-08-19 17:33, Ard Biesheuvel wrote:

Hi Hans,

On Sun, 4 Aug 2019 at 13:00, Hans de Goede  wrote:


Hi All,

While testing 5.3-rc2 on an Irbis TW90 Intel Cherry Trail based
tablet I noticed that it does not boot on this device.

A git bisect points to commit 166a2809d65b ("tpm: Don't duplicate
events from the final event log in the TCG2 log")

And I can confirm that reverting just that single commit makes
the TW90 boot again.

This machine uses AptIO firmware with base component versions
of: UEFI 2.4 PI 1.3. I've tried to reproduce the problem on
a Teclast X80 Pro which is also CHT based and also uses AptIO
firmware with the same base components. But it does not reproduce
there. Neither does the problem reproduce on a CHT tablet using
InsideH20 based firmware.

Note that these devices have a software/firmware TPM-2.0
implementation, they do not have an actual TPM chip.

Comparing TPM firmware setting between the 2 AptIO based
tablets the settings are identical, but the troublesome
TW90 does have some more setting then the X80, it has
the following settings which are not shown on the X80:

Active PCR banks:   SHA-1 (read only)
Available PCR banks:SHA-1,SHA256  (read only)
TPM2.0 UEFI SPEC version:   TCG_2 (other possible setting: TCG_1_2
Physical Presence SPEC ver: 1.2   (other possible setting: 1.3)

I have the feeling that at least the first 2 indicate that
the previous win10 installation has actually used the
TPM, where as on the X80 the TPM is uninitialized.
Note this is just a hunch I could be completely wrong.

I would be happy to run any commands to try and debug this
or to build a kernel with some patches to gather more info.

Note any kernel patches to printk some debug stuff need
to be based on 5.3 with 166a2809d65b reverted, without that
reverted the device will not boot, and thus I cannot collect
logs without it reverted.



Are you booting a 64-bit kernel on 32-bit firmware?


Yes you are right, I must say that this is somewhat surprising
most Cherry Trail devices do use 64 bit firmware (where as Bay Trail
typically uses 32 bit). But I just checked efibootmgr output and it
says it is booting: \EFI\FEDORA\SHIMIA32.EFI so yeah 32 bit firmware.

Recent Fedora releases take care of this so seamlessly I did not
even realize...



OK, so we'll have to find out how this patch affects 64-bit code
running on 32-bit firmware. The only EFI call in that patch is
get_config_table(), which is not actually a EFI boot service call but
a EFI stub helper that parses the config table array in the EFI system
table.


Ok, the problem indeed is the new get_efi_config_table() helper, it
does not make any calls, but it does interpret some structs which
have different sized members depending on if the firmware is 32 or 64 bit.

I've prepared a patch fixing this which I will send out after this mail.

Regards,

Hans



Re: 5.3 boot regression caused by 5.3 TPM changes

2019-08-07 Thread Hans de Goede

Hi,

On 07-08-19 22:13, Hans de Goede wrote:

Hi,

On 07-08-19 21:58, Hans de Goede wrote:

Hi,

On 05-08-19 18:01, Ard Biesheuvel wrote:

On Sun, 4 Aug 2019 at 19:12, Hans de Goede  wrote:


Hi,

On 04-08-19 17:33, Ard Biesheuvel wrote:

Hi Hans,

On Sun, 4 Aug 2019 at 13:00, Hans de Goede  wrote:


Hi All,

While testing 5.3-rc2 on an Irbis TW90 Intel Cherry Trail based
tablet I noticed that it does not boot on this device.

A git bisect points to commit 166a2809d65b ("tpm: Don't duplicate
events from the final event log in the TCG2 log")

And I can confirm that reverting just that single commit makes
the TW90 boot again.

This machine uses AptIO firmware with base component versions
of: UEFI 2.4 PI 1.3. I've tried to reproduce the problem on
a Teclast X80 Pro which is also CHT based and also uses AptIO
firmware with the same base components. But it does not reproduce
there. Neither does the problem reproduce on a CHT tablet using
InsideH20 based firmware.

Note that these devices have a software/firmware TPM-2.0
implementation, they do not have an actual TPM chip.

Comparing TPM firmware setting between the 2 AptIO based
tablets the settings are identical, but the troublesome
TW90 does have some more setting then the X80, it has
the following settings which are not shown on the X80:

Active PCR banks:   SHA-1 (read only)
Available PCR banks:    SHA-1,SHA256  (read only)
TPM2.0 UEFI SPEC version:   TCG_2 (other possible setting: TCG_1_2
Physical Presence SPEC ver: 1.2   (other possible setting: 1.3)

I have the feeling that at least the first 2 indicate that
the previous win10 installation has actually used the
TPM, where as on the X80 the TPM is uninitialized.
Note this is just a hunch I could be completely wrong.

I would be happy to run any commands to try and debug this
or to build a kernel with some patches to gather more info.

Note any kernel patches to printk some debug stuff need
to be based on 5.3 with 166a2809d65b reverted, without that
reverted the device will not boot, and thus I cannot collect
logs without it reverted.



Are you booting a 64-bit kernel on 32-bit firmware?


Yes you are right, I must say that this is somewhat surprising
most Cherry Trail devices do use 64 bit firmware (where as Bay Trail
typically uses 32 bit). But I just checked efibootmgr output and it
says it is booting: \EFI\FEDORA\SHIMIA32.EFI so yeah 32 bit firmware.

Recent Fedora releases take care of this so seamlessly I did not
even realize...



OK, so we'll have to find out how this patch affects 64-bit code
running on 32-bit firmware.


I was not sure this really is a 32 bit firmware issue, as I believed
I saw 5.3 running fine on other 32 bit firmware devices, so I tried
this on another device with 32 bit UEFI and you're right this is a
32 bit issue.


The only EFI call in that patch is
get_config_table(), which is not actually a EFI boot service call but
a EFI stub helper that parses the config table array in the EFI system
table.


Well get_efi_config_table() is a new function in 5.3, introduced
specifically for the 166a2809d65b ("tpm: Don't duplicate events from the
final event log in the TCG2 log") commit.

It was introduced in commit 82d736ac56d7 ("Abstract out support for
locating an EFI config table") and after taking a good look at this
commit I'm pretty confident to say that the new get_efi_config_table()
function is the problem, as it is broken in multiple ways.

In itself the new get_efi_config_table() is just factoring out some
code used in drivers/firmware/efi/libstub/fdt.c into a new helper
for reuse and not making any functional changes to the factored out
code.

The problem is that the old code which it factors out contains a number
of assumptions which are true in the get_fdt() context from which it
was called but are not true when used in more generic code as is done
from the 166a2809d65b ("tpm: Don't duplicate events from the
final event log in the TCG2 log") commit.

There are 2 problems with the new get_efi_config_table() function:

1) sys_table->tables contains a physical address, we cannot just
cast that to a pointer and deref it, it needs to be early_memremap-ed
and then we deref the mapping. I'm somewhat amazed that this works
at all for the 64 bit case, but apparently it does.

2) sys_table->tables points to either an array of either
efi_config_table_64_t structd or an array of efi_config_table_32_t
structs.  efi_config_table_t is a generic type for storing information
when parsing it should NOT be used for reading the actual tables
as they come from the firmware when parsing! Now efi_config_table_t
happens to be an exact match for efi_config_table_64_t when building
an x86_64 kernel, so this happens to work for the 64 bit firmware case.

The properway to deal with this would be to use the existing
efi_config_parse_tables() functionality from drivers/firmware/efi/efi.c
by adding entry for the LIN

Re: 5.3 boot regression caused by 5.3 TPM changes

2019-08-07 Thread Hans de Goede

Hi,

On 07-08-19 21:58, Hans de Goede wrote:

Hi,

On 05-08-19 18:01, Ard Biesheuvel wrote:

On Sun, 4 Aug 2019 at 19:12, Hans de Goede  wrote:


Hi,

On 04-08-19 17:33, Ard Biesheuvel wrote:

Hi Hans,

On Sun, 4 Aug 2019 at 13:00, Hans de Goede  wrote:


Hi All,

While testing 5.3-rc2 on an Irbis TW90 Intel Cherry Trail based
tablet I noticed that it does not boot on this device.

A git bisect points to commit 166a2809d65b ("tpm: Don't duplicate
events from the final event log in the TCG2 log")

And I can confirm that reverting just that single commit makes
the TW90 boot again.

This machine uses AptIO firmware with base component versions
of: UEFI 2.4 PI 1.3. I've tried to reproduce the problem on
a Teclast X80 Pro which is also CHT based and also uses AptIO
firmware with the same base components. But it does not reproduce
there. Neither does the problem reproduce on a CHT tablet using
InsideH20 based firmware.

Note that these devices have a software/firmware TPM-2.0
implementation, they do not have an actual TPM chip.

Comparing TPM firmware setting between the 2 AptIO based
tablets the settings are identical, but the troublesome
TW90 does have some more setting then the X80, it has
the following settings which are not shown on the X80:

Active PCR banks:   SHA-1 (read only)
Available PCR banks:    SHA-1,SHA256  (read only)
TPM2.0 UEFI SPEC version:   TCG_2 (other possible setting: TCG_1_2
Physical Presence SPEC ver: 1.2   (other possible setting: 1.3)

I have the feeling that at least the first 2 indicate that
the previous win10 installation has actually used the
TPM, where as on the X80 the TPM is uninitialized.
Note this is just a hunch I could be completely wrong.

I would be happy to run any commands to try and debug this
or to build a kernel with some patches to gather more info.

Note any kernel patches to printk some debug stuff need
to be based on 5.3 with 166a2809d65b reverted, without that
reverted the device will not boot, and thus I cannot collect
logs without it reverted.



Are you booting a 64-bit kernel on 32-bit firmware?


Yes you are right, I must say that this is somewhat surprising
most Cherry Trail devices do use 64 bit firmware (where as Bay Trail
typically uses 32 bit). But I just checked efibootmgr output and it
says it is booting: \EFI\FEDORA\SHIMIA32.EFI so yeah 32 bit firmware.

Recent Fedora releases take care of this so seamlessly I did not
even realize...



OK, so we'll have to find out how this patch affects 64-bit code
running on 32-bit firmware.


I was not sure this really is a 32 bit firmware issue, as I believed
I saw 5.3 running fine on other 32 bit firmware devices, so I tried
this on another device with 32 bit UEFI and you're right this is a
32 bit issue.


The only EFI call in that patch is
get_config_table(), which is not actually a EFI boot service call but
a EFI stub helper that parses the config table array in the EFI system
table.


Well get_efi_config_table() is a new function in 5.3, introduced
specifically for the 166a2809d65b ("tpm: Don't duplicate events from the
final event log in the TCG2 log") commit.

It was introduced in commit 82d736ac56d7 ("Abstract out support for
locating an EFI config table") and after taking a good look at this
commit I'm pretty confident to say that the new get_efi_config_table()
function is the problem, as it is broken in multiple ways.

In itself the new get_efi_config_table() is just factoring out some
code used in drivers/firmware/efi/libstub/fdt.c into a new helper
for reuse and not making any functional changes to the factored out
code.

The problem is that the old code which it factors out contains a number
of assumptions which are true in the get_fdt() context from which it
was called but are not true when used in more generic code as is done
from the 166a2809d65b ("tpm: Don't duplicate events from the
final event log in the TCG2 log") commit.

There are 2 problems with the new get_efi_config_table() function:

1) sys_table->tables contains a physical address, we cannot just
cast that to a pointer and deref it, it needs to be early_memremap-ed
and then we deref the mapping. I'm somewhat amazed that this works
at all for the 64 bit case, but apparently it does.

2) sys_table->tables points to either an array of either
efi_config_table_64_t structd or an array of efi_config_table_32_t
structs.  efi_config_table_t is a generic type for storing information
when parsing it should NOT be used for reading the actual tables
as they come from the firmware when parsing! Now efi_config_table_t
happens to be an exact match for efi_config_table_64_t when building
an x86_64 kernel, so this happens to work for the 64 bit firmware case.

The properway to deal with this would be to use the existing
efi_config_parse_tables() functionality from drivers/firmware/efi/efi.c
by adding entry for the LINUX_EFI_TPM_FINAL_LOG_GUID to the
common_tables[

Re: 5.3 boot regression caused by 5.3 TPM changes

2019-08-07 Thread Hans de Goede

Hi,

On 05-08-19 18:01, Ard Biesheuvel wrote:

On Sun, 4 Aug 2019 at 19:12, Hans de Goede  wrote:


Hi,

On 04-08-19 17:33, Ard Biesheuvel wrote:

Hi Hans,

On Sun, 4 Aug 2019 at 13:00, Hans de Goede  wrote:


Hi All,

While testing 5.3-rc2 on an Irbis TW90 Intel Cherry Trail based
tablet I noticed that it does not boot on this device.

A git bisect points to commit 166a2809d65b ("tpm: Don't duplicate
events from the final event log in the TCG2 log")

And I can confirm that reverting just that single commit makes
the TW90 boot again.

This machine uses AptIO firmware with base component versions
of: UEFI 2.4 PI 1.3. I've tried to reproduce the problem on
a Teclast X80 Pro which is also CHT based and also uses AptIO
firmware with the same base components. But it does not reproduce
there. Neither does the problem reproduce on a CHT tablet using
InsideH20 based firmware.

Note that these devices have a software/firmware TPM-2.0
implementation, they do not have an actual TPM chip.

Comparing TPM firmware setting between the 2 AptIO based
tablets the settings are identical, but the troublesome
TW90 does have some more setting then the X80, it has
the following settings which are not shown on the X80:

Active PCR banks:   SHA-1 (read only)
Available PCR banks:SHA-1,SHA256  (read only)
TPM2.0 UEFI SPEC version:   TCG_2 (other possible setting: TCG_1_2
Physical Presence SPEC ver: 1.2   (other possible setting: 1.3)

I have the feeling that at least the first 2 indicate that
the previous win10 installation has actually used the
TPM, where as on the X80 the TPM is uninitialized.
Note this is just a hunch I could be completely wrong.

I would be happy to run any commands to try and debug this
or to build a kernel with some patches to gather more info.

Note any kernel patches to printk some debug stuff need
to be based on 5.3 with 166a2809d65b reverted, without that
reverted the device will not boot, and thus I cannot collect
logs without it reverted.



Are you booting a 64-bit kernel on 32-bit firmware?


Yes you are right, I must say that this is somewhat surprising
most Cherry Trail devices do use 64 bit firmware (where as Bay Trail
typically uses 32 bit). But I just checked efibootmgr output and it
says it is booting: \EFI\FEDORA\SHIMIA32.EFI so yeah 32 bit firmware.

Recent Fedora releases take care of this so seamlessly I did not
even realize...



OK, so we'll have to find out how this patch affects 64-bit code
running on 32-bit firmware.


I was not sure this really is a 32 bit firmware issue, as I believed
I saw 5.3 running fine on other 32 bit firmware devices, so I tried
this on another device with 32 bit UEFI and you're right this is a
32 bit issue.


The only EFI call in that patch is
get_config_table(), which is not actually a EFI boot service call but
a EFI stub helper that parses the config table array in the EFI system
table.


Well get_efi_config_table() is a new function in 5.3, introduced
specifically for the 166a2809d65b ("tpm: Don't duplicate events from the
final event log in the TCG2 log") commit.

It was introduced in commit 82d736ac56d7 ("Abstract out support for
locating an EFI config table") and after taking a good look at this
commit I'm pretty confident to say that the new get_efi_config_table()
function is the problem, as it is broken in multiple ways.

In itself the new get_efi_config_table() is just factoring out some
code used in drivers/firmware/efi/libstub/fdt.c into a new helper
for reuse and not making any functional changes to the factored out
code.

The problem is that the old code which it factors out contains a number
of assumptions which are true in the get_fdt() context from which it
was called but are not true when used in more generic code as is done
from the 166a2809d65b ("tpm: Don't duplicate events from the
final event log in the TCG2 log") commit.

There are 2 problems with the new get_efi_config_table() function:

1) sys_table->tables contains a physical address, we cannot just
cast that to a pointer and deref it, it needs to be early_memremap-ed
and then we deref the mapping. I'm somewhat amazed that this works
at all for the 64 bit case, but apparently it does.

2) sys_table->tables points to either an array of either
efi_config_table_64_t structd or an array of efi_config_table_32_t
structs.  efi_config_table_t is a generic type for storing information
when parsing it should NOT be used for reading the actual tables
as they come from the firmware when parsing! Now efi_config_table_t
happens to be an exact match for efi_config_table_64_t when building
an x86_64 kernel, so this happens to work for the 64 bit firmware case.

The properway to deal with this would be to use the existing
efi_config_parse_tables() functionality from drivers/firmware/efi/efi.c
by adding entry for the LINUX_EFI_TPM_FINAL_LOG_GUID to the
common_tables[] array in drivers/firmware/efi/efi.c and mak

Re: 5.3 boot regression caused by 5.3 TPM changes

2019-08-06 Thread Hans de Goede

Hi,

On 06-08-19 17:53, Chris Coulson wrote:

Hi,

On 04/08/2019 11:00, Hans de Goede wrote:

Hi All,

While testing 5.3-rc2 on an Irbis TW90 Intel Cherry Trail based
tablet I noticed that it does not boot on this device.

A git bisect points to commit 166a2809d65b ("tpm: Don't duplicate
events from the final event log in the TCG2 log")

And I can confirm that reverting just that single commit makes
the TW90 boot again.

This machine uses AptIO firmware with base component versions
of: UEFI 2.4 PI 1.3. I've tried to reproduce the problem on
a Teclast X80 Pro which is also CHT based and also uses AptIO
firmware with the same base components. But it does not reproduce
there. Neither does the problem reproduce on a CHT tablet using
InsideH20 based firmware.

Note that these devices have a software/firmware TPM-2.0
implementation, they do not have an actual TPM chip.

Comparing TPM firmware setting between the 2 AptIO based
tablets the settings are identical, but the troublesome
TW90 does have some more setting then the X80, it has
the following settings which are not shown on the X80:

Active PCR banks:   SHA-1 (read only)
Available PCR banks:    SHA-1,SHA256  (read only)
TPM2.0 UEFI SPEC version:   TCG_2 (other possible setting: TCG_1_2
Physical Presence SPEC ver: 1.2   (other possible setting: 1.3)

I have the feeling that at least the first 2 indicate that
the previous win10 installation has actually used the
TPM, where as on the X80 the TPM is uninitialized.
Note this is just a hunch I could be completely wrong.

I would be happy to run any commands to try and debug this
or to build a kernel with some patches to gather more info.

Note any kernel patches to printk some debug stuff need
to be based on 5.3 with 166a2809d65b reverted, without that
reverted the device will not boot, and thus I cannot collect
logs without it reverted.

Regards,

Hans

Do you think this might be the same issue as 
https://marc.info/?l=linux-integrity=155968949020639 
<https://marc.info/?l=linux-integrity=155968949020639=2>?


I was hoping it would be the same issue, so I tested a 5.3 kernel
with that patch added, but unfortunately it still crashes on
the Irbis TW90.

Regards,

Hans



Re: 5.3 boot regression caused by 5.3 TPM changes

2019-08-04 Thread Hans de Goede

Hi,

On 04-08-19 17:33, Ard Biesheuvel wrote:

Hi Hans,

On Sun, 4 Aug 2019 at 13:00, Hans de Goede  wrote:


Hi All,

While testing 5.3-rc2 on an Irbis TW90 Intel Cherry Trail based
tablet I noticed that it does not boot on this device.

A git bisect points to commit 166a2809d65b ("tpm: Don't duplicate
events from the final event log in the TCG2 log")

And I can confirm that reverting just that single commit makes
the TW90 boot again.

This machine uses AptIO firmware with base component versions
of: UEFI 2.4 PI 1.3. I've tried to reproduce the problem on
a Teclast X80 Pro which is also CHT based and also uses AptIO
firmware with the same base components. But it does not reproduce
there. Neither does the problem reproduce on a CHT tablet using
InsideH20 based firmware.

Note that these devices have a software/firmware TPM-2.0
implementation, they do not have an actual TPM chip.

Comparing TPM firmware setting between the 2 AptIO based
tablets the settings are identical, but the troublesome
TW90 does have some more setting then the X80, it has
the following settings which are not shown on the X80:

Active PCR banks:   SHA-1 (read only)
Available PCR banks:SHA-1,SHA256  (read only)
TPM2.0 UEFI SPEC version:   TCG_2 (other possible setting: TCG_1_2
Physical Presence SPEC ver: 1.2   (other possible setting: 1.3)

I have the feeling that at least the first 2 indicate that
the previous win10 installation has actually used the
TPM, where as on the X80 the TPM is uninitialized.
Note this is just a hunch I could be completely wrong.

I would be happy to run any commands to try and debug this
or to build a kernel with some patches to gather more info.

Note any kernel patches to printk some debug stuff need
to be based on 5.3 with 166a2809d65b reverted, without that
reverted the device will not boot, and thus I cannot collect
logs without it reverted.



Are you booting a 64-bit kernel on 32-bit firmware?


Yes you are right, I must say that this is somewhat surprising
most Cherry Trail devices do use 64 bit firmware (where as Bay Trail
typically uses 32 bit). But I just checked efibootmgr output and it
says it is booting: \EFI\FEDORA\SHIMIA32.EFI so yeah 32 bit firmware.

Recent Fedora releases take care of this so seamlessly I did not
even realize...

Regards,

Hans


5.3 boot regression caused by 5.3 TPM changes

2019-08-04 Thread Hans de Goede

Hi All,

While testing 5.3-rc2 on an Irbis TW90 Intel Cherry Trail based
tablet I noticed that it does not boot on this device.

A git bisect points to commit 166a2809d65b ("tpm: Don't duplicate
events from the final event log in the TCG2 log")

And I can confirm that reverting just that single commit makes
the TW90 boot again.

This machine uses AptIO firmware with base component versions
of: UEFI 2.4 PI 1.3. I've tried to reproduce the problem on
a Teclast X80 Pro which is also CHT based and also uses AptIO
firmware with the same base components. But it does not reproduce
there. Neither does the problem reproduce on a CHT tablet using
InsideH20 based firmware.

Note that these devices have a software/firmware TPM-2.0
implementation, they do not have an actual TPM chip.

Comparing TPM firmware setting between the 2 AptIO based
tablets the settings are identical, but the troublesome
TW90 does have some more setting then the X80, it has
the following settings which are not shown on the X80:

Active PCR banks:   SHA-1 (read only)
Available PCR banks:SHA-1,SHA256  (read only)
TPM2.0 UEFI SPEC version:   TCG_2 (other possible setting: TCG_1_2
Physical Presence SPEC ver: 1.2   (other possible setting: 1.3)

I have the feeling that at least the first 2 indicate that
the previous win10 installation has actually used the
TPM, where as on the X80 the TPM is uninitialized.
Note this is just a hunch I could be completely wrong.

I would be happy to run any commands to try and debug this
or to build a kernel with some patches to gather more info.

Note any kernel patches to printk some debug stuff need
to be based on 5.3 with 166a2809d65b reverted, without that
reverted the device will not boot, and thus I cannot collect
logs without it reverted.

Regards,

Hans


[PATCH] efi/bgrt: Drop BGRT status field reserved bits check

2019-05-29 Thread Hans de Goede
Starting with ACPI 6.2 bits 1 and 2 of the BGRT status field are no longer
reserved. These bits are now used to indicate if the image needs to be
rotated before being displayed.

The first device using these bits has now shown up (the GPD MicroPC) and
the reserved bits check causes us to reject the valid BGRT table on this
device.

Rather then changing the reserved bits check, allowing only the 2 new bits,
instead just completely remove it so that we do not end up with a similar
problem when more bits are added in the future.

Signed-off-by: Hans de Goede 
---
 drivers/firmware/efi/efi-bgrt.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/firmware/efi/efi-bgrt.c b/drivers/firmware/efi/efi-bgrt.c
index a2384184a7de..b07c17643210 100644
--- a/drivers/firmware/efi/efi-bgrt.c
+++ b/drivers/firmware/efi/efi-bgrt.c
@@ -47,11 +47,6 @@ void __init efi_bgrt_init(struct acpi_table_header *table)
   bgrt->version);
goto out;
}
-   if (bgrt->status & 0xfe) {
-   pr_notice("Ignoring BGRT: reserved status bits are non-zero 
%u\n",
-  bgrt->status);
-   goto out;
-   }
if (bgrt->image_type != 0) {
pr_notice("Ignoring BGRT: invalid image type %u (expected 0)\n",
   bgrt->image_type);
-- 
2.21.0



[PATCH v2] efi/x86: Call efi_parse_options() from efi_main()

2018-09-12 Thread Hans de Goede
Before this commit we were only calling efi_parse_options() from
make_boot_params(), but make_boot_params() only gets called if the
kernel gets booted directly as an EFI executable. So when booted through
e.g. grub we ended up not parsing the commandline in the boot code.

This makes the drivers/firmware/efi/libstub code ignore the "quiet"
commandline argument resulting in the following message being printed:
"EFI stub: UEFI Secure Boot is enabled."

Despite the quiet request. This commits adds an extra call to
efi_parse_options() to efi_main() to make sure that the options are
always processed. This fixes quiet not working.

This also fixes the libstub code ignoring nokaslr and efi=nochunk.

Reported-by: Peter Robinson 
Signed-off-by: Hans de Goede 
---
Changes in v2:
-Fix a compiler warning on 32 bit builds about casting a non pointer
 sized integer to a pointer
---
 arch/x86/boot/compressed/eboot.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 1458b1700fc7..8b4c5e001157 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -738,6 +738,7 @@ efi_main(struct efi_config *c, struct boot_params 
*boot_params)
struct desc_struct *desc;
void *handle;
efi_system_table_t *_table;
+   unsigned long cmdline_paddr;
 
efi_early = c;
 
@@ -755,6 +756,15 @@ efi_main(struct efi_config *c, struct boot_params 
*boot_params)
else
setup_boot_services32(efi_early);
 
+   /*
+* make_boot_params() may have been called before efi_main(), in which
+* case this is the second time we parse the cmdline. This is ok,
+* parsing the cmdline multiple times does not have side-effects.
+*/
+   cmdline_paddr = ((u64)hdr->cmd_line_ptr |
+((u64)boot_params->ext_cmd_line_ptr << 32));
+   efi_parse_options((char *)cmdline_paddr);
+
/*
 * If the boot loader gave us a value for secure_boot then we use that,
 * otherwise we ask the BIOS.
-- 
2.19.0.rc0



Re: [PATCH] efi/x86: Call efi_parse_options() from efi_main()

2018-09-12 Thread Hans de Goede

Hi,

On 12-09-18 17:06, Ard Biesheuvel wrote:

On 12 September 2018 at 15:18, Hans de Goede  wrote:

Before this commit we were only calling efi_parse_options() from
make_boot_params(), but make_boot_params() only gets called if the
kernel gets booted directly as an EFI executable. So when booted through
e.g. grub we ended up not parsing the commandline in the boot code.

This makes the drivers/firmware/efi/libstub code ignore the "quiet"
commandline argument resulting in the following message being printed:
"EFI stub: UEFI Secure Boot is enabled."

Despite the quiet request. This commits adds an extra call to
efi_parse_options() to efi_main() to make sure that the options are
always processed. This fixes quiet not working.

This also fixes the libstub code ignoring nokaslr and efi=nochunk.

Reported-by: Peter Robinson 
Signed-off-by: Hans de Goede 
---
  arch/x86/boot/compressed/eboot.c | 10 ++
  1 file changed, 10 insertions(+)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index aaabf979cbd9..a4c85d37adc9 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -738,6 +738,7 @@ efi_main(struct efi_config *c, struct boot_params 
*boot_params)
 struct desc_struct *desc;
 void *handle;
 efi_system_table_t *_table;
+   const char *cmdline_ptr;

 efi_early = c;

@@ -755,6 +756,15 @@ efi_main(struct efi_config *c, struct boot_params 
*boot_params)
 else
 setup_boot_services32(efi_early);

+   /*
+* make_boot_params() may have been called before efi_main(), in which
+* case this is the second time we parse the cmdline. This is ok,
+* parsing the cmdline multiple times does not have side-effects.
+*/
+   cmdline_ptr = (const char *)((u64)hdr->cmd_line_ptr |
+   ((u64)boot_params->ext_cmd_line_ptr << 32));
+   efi_parse_options(cmdline_ptr);
+


This triggers a warning on 32-bit because sizeof(void*) != sizeof(u64)


Grumble, ok so looking at what other code accessing  hdr->cmd_line_ptr +
boot_params->ext_cmd_line_ptr is most code seems to store it in an
unsigned long. So here is what I suggest for v2:

--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -738,6 +738,7 @@ efi_main(struct efi_config *c, struct boot_params 
*boot_params)
struct desc_struct *desc;
void *handle;
efi_system_table_t *_table;
+   unsigned long cmdline_paddr;

efi_early = c;

@@ -755,6 +756,15 @@ efi_main(struct efi_config *c, struct boot_params 
*boot_params)
else
setup_boot_services32(efi_early);

+   /*
+* make_boot_params() may have been called before efi_main(), in which
+* case this is the second time we parse the cmdline. This is ok,
+* parsing the cmdline multiple times does not have side-effects.
+*/
+   cmdline_paddr = ((u64)hdr->cmd_line_ptr |
+((u64)boot_params->ext_cmd_line_ptr << 32));
+   efi_parse_options((char *)cmdline_paddr);
+
/*
 * If the boot loader gave us a value for secure_boot then we use that,
 * otherwise we ask the BIOS.

If that looks ok to you I will send out a proper v2 with this.

Regards,

Hans




[PATCH] efi/x86: Call efi_parse_options() from efi_main()

2018-09-12 Thread Hans de Goede
Before this commit we were only calling efi_parse_options() from
make_boot_params(), but make_boot_params() only gets called if the
kernel gets booted directly as an EFI executable. So when booted through
e.g. grub we ended up not parsing the commandline in the boot code.

This makes the drivers/firmware/efi/libstub code ignore the "quiet"
commandline argument resulting in the following message being printed:
"EFI stub: UEFI Secure Boot is enabled."

Despite the quiet request. This commits adds an extra call to
efi_parse_options() to efi_main() to make sure that the options are
always processed. This fixes quiet not working.

This also fixes the libstub code ignoring nokaslr and efi=nochunk.

Reported-by: Peter Robinson 
Signed-off-by: Hans de Goede 
---
 arch/x86/boot/compressed/eboot.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index aaabf979cbd9..a4c85d37adc9 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -738,6 +738,7 @@ efi_main(struct efi_config *c, struct boot_params 
*boot_params)
struct desc_struct *desc;
void *handle;
efi_system_table_t *_table;
+   const char *cmdline_ptr;
 
efi_early = c;
 
@@ -755,6 +756,15 @@ efi_main(struct efi_config *c, struct boot_params 
*boot_params)
else
setup_boot_services32(efi_early);
 
+   /*
+* make_boot_params() may have been called before efi_main(), in which
+* case this is the second time we parse the cmdline. This is ok,
+* parsing the cmdline multiple times does not have side-effects.
+*/
+   cmdline_ptr = (const char *)((u64)hdr->cmd_line_ptr |
+   ((u64)boot_params->ext_cmd_line_ptr << 32));
+   efi_parse_options(cmdline_ptr);
+
/*
 * If the boot loader gave us a value for secure_boot then we use that,
 * otherwise we ask the BIOS.
-- 
2.19.0.rc0



Re: [REGRESSION] boot-screen override by "34db50e55656 efifb: Copy the ACPI BGRT"

2018-09-12 Thread Hans de Goede

Hi,

On 03-09-18 17:11, David Herrmann wrote:

Hey

On Mon, Sep 3, 2018 at 4:47 PM Hans de Goede  wrote:


Hi,

On 03-09-18 16:16, Bartlomiej Zolnierkiewicz wrote:


Hi,

On Monday, September 03, 2018 03:23:38 PM David Herrmann wrote:

Hey

Since this commit:

  34db50e55656 efifb: Copy the ACPI BGRT

the kernel will override boot-splashs unasked. This breaks the
graphical boot-process on our setups. In particular, we have a setup
where an efi-boot-entry draws the early boot-splash on-screen, then
hands-over to the linux-kernel + initrd. The boot-splash daemon in the
initrd then takes over control of possible animations.

With the mentioned commit compiled in, the kernel will redraw the
firmware logo on screen at a random time without any way to intervene.


You have CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y (the deferred
console takeover support introduced in v4,19-rc1). I assume that this
is intended?


What is the intention of this commit? Why is the kernel re-drawing the
firmware logo unasked? If someone during the boot-process draws
content on the screen, I would prefer if the kernel does not clear
that on driver load.


+/*
+ * If fbcon deffered console takeover is configured, the intent is for the
+ * framebuffer to show the boot graphics (e.g. vendor logo) until there is some
+ * (error) message to display. But the boot graphics may have been destroyed by
+ * e.g. option ROM output, detect this and restore the boot graphics.
+ */
+#if defined CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER && \
+defined CONFIG_ACPI_BGRT
...
+static void efifb_show_boot_graphics(struct fb_info *info)
...
+#else
+static inline void efifb_show_boot_graphics(struct fb_info *info) {}
+#endif


Can we either provide an option to disable this feature, or revert the commit?


Hans?


We use the ACPI bgrt extension to get the logo to draw and then
draw it since some devices rely on the OS to draw it and otherwise we
just end up with a blackscreen when doing silent / flickerfree boot.

Ideally you would be able to get your vendor to put the logo in firmware
in the ACPI bgrt extension, then you also do not need to play any tricks
with an EFI binary drawing your own logo. But I can understand if you don't
have control over this, so you need to do this with the EFI binary trick.

I can also understand that you want to use deferred console takeover
in a setup like yours to avoid fbcon messing up what is on the display
during boot, that is exactly what it is for. So I think a reasonable
approach here is to add a kernel commandline option, say:

video=efifb:nobgrt

David, would that work for you?


That would be perfect!


Ok, I just send out a patch for this with you in the Cc.

Sorry for taking a bit long to write the patch.

Regards,

Hans



Re: [REGRESSION] boot-screen override by "34db50e55656 efifb: Copy the ACPI BGRT"

2018-09-03 Thread Hans de Goede

Hi,

On 03-09-18 16:16, Bartlomiej Zolnierkiewicz wrote:


Hi,

On Monday, September 03, 2018 03:23:38 PM David Herrmann wrote:

Hey

Since this commit:

 34db50e55656 efifb: Copy the ACPI BGRT

the kernel will override boot-splashs unasked. This breaks the
graphical boot-process on our setups. In particular, we have a setup
where an efi-boot-entry draws the early boot-splash on-screen, then
hands-over to the linux-kernel + initrd. The boot-splash daemon in the
initrd then takes over control of possible animations.

With the mentioned commit compiled in, the kernel will redraw the
firmware logo on screen at a random time without any way to intervene.


You have CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y (the deferred
console takeover support introduced in v4,19-rc1). I assume that this
is intended?


What is the intention of this commit? Why is the kernel re-drawing the
firmware logo unasked? If someone during the boot-process draws
content on the screen, I would prefer if the kernel does not clear
that on driver load.


+/*
+ * If fbcon deffered console takeover is configured, the intent is for the
+ * framebuffer to show the boot graphics (e.g. vendor logo) until there is some
+ * (error) message to display. But the boot graphics may have been destroyed by
+ * e.g. option ROM output, detect this and restore the boot graphics.
+ */
+#if defined CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER && \
+defined CONFIG_ACPI_BGRT
...
+static void efifb_show_boot_graphics(struct fb_info *info)
...
+#else
+static inline void efifb_show_boot_graphics(struct fb_info *info) {}
+#endif


Can we either provide an option to disable this feature, or revert the commit?


Hans?


We use the ACPI bgrt extension to get the logo to draw and then
draw it since some devices rely on the OS to draw it and otherwise we
just end up with a blackscreen when doing silent / flickerfree boot.

Ideally you would be able to get your vendor to put the logo in firmware
in the ACPI bgrt extension, then you also do not need to play any tricks
with an EFI binary drawing your own logo. But I can understand if you don't
have control over this, so you need to do this with the EFI binary trick.

I can also understand that you want to use deferred console takeover
in a setup like yours to avoid fbcon messing up what is on the display
during boot, that is exactly what it is for. So I think a reasonable
approach here is to add a kernel commandline option, say:

video=efifb:nobgrt

David, would that work for you?

Regards,

Hans


Re: [PATCH 0/6] efi/x86 mixed mode cleanups

2018-07-12 Thread Hans de Goede

Hi,

On 12-07-18 14:21, Ard Biesheuvel wrote:

This series contains some fixes and cleanups for mixed-mode UEFI on x86.

Patch #1 adds the missing locking in the runtime service wrapper code for
mixed mode. This was found by inspection rather than having been reported
but could be a candidate for -stable nonetheless.

Patch #2 merges the remaining 32/64-bit specific parts of the setup_efi_pci
routine.

Patches #3 and #4 do the same for the UGA draw protocol discovery routines.

Patch #5 fixes a latent bug in the UGA draw code.

Patch #6 helps unused code paths to be optimized away on configurations
that don't need them (32-bit only and 64-bit only)


I've given a kernel with these patches a quick spin running in mixed
mode on a Bay Trail based tablet:

Tested-by: Hans de Goede 

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [GIT PULL 0/1] EFI mixed mode fix for v4.18

2018-07-11 Thread Hans de Goede

Hi,

On 11-07-18 12:13, Ingo Molnar wrote:


* Ard Biesheuvel  wrote:


The following changes since commit 1e4b044d22517cae7047c99038abb23243ca:

   Linux 4.18-rc4 (2018-07-08 16:34:02 -0700)

are available in the Git repository at:

   git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git tags/efi-urgent

for you to fetch changes up to d7f2e972e702d329fe11d6956df99dfc31211c25:

   efi/x86: remove pointless call to PciIo->Attributes() (2018-07-11 10:52:46 
+0200)


A single fix for the x86 PCI I/O protocol handling code that got
broken for mixed mode (64-bit Linux/x86 on 32-bit UEFI) after a
fix was applied in -rc2 to fix it for ordinary 64-bit Linux/x86.


Just curious, because it's unclear from the changelog, what was the symptom, a
boot hang, instant reboot, or some other misbehavior? Also, what's the scope of
the fix: were all 64-bit on 32-bit UEFI mixed-mode bootups affected, or only a
certain subset?


The problem was a reboot (resulting in a boot loop). I may have tested this
on multiple Bay Trail based devices, I don't remember but it was an issue on
Bay Trail devices, which typically use a 32 bit UEFI even though they have a
64 bit capable CPU. There are some rare Bay Trail devices with a 64 bit UEFI
but they are the exception.

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/2] efi/bgrt: Drop __initdata from bgrt_image_size

2018-07-02 Thread Hans de Goede

Bartlomiej,

Now that the fbcon deferred console takeover patches have been
merged I believe this series can be merged too ?

Note the first patch has an ack from Ard for merging the
1 line efi change through the fbdev tree.

Regards,

Hans


On 18-06-18 17:13, Hans de Goede wrote:

bgrt_image_size is necessary to (optionally) show the boot graphics from
the efifb code. The efifb driver is a platform driver, using a normal
driver probe() driver callback. So even though it is always builtin it
cannot reference __initdata.

Acked-by: Ard Biesheuvel 
Signed-off-by: Hans de Goede 
---
  drivers/firmware/efi/efi-bgrt.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/efi-bgrt.c b/drivers/firmware/efi/efi-bgrt.c
index 50793fda7819..b22ccfb0c991 100644
--- a/drivers/firmware/efi/efi-bgrt.c
+++ b/drivers/firmware/efi/efi-bgrt.c
@@ -20,7 +20,7 @@
  #include 
  
  struct acpi_table_bgrt bgrt_tab;

-size_t __initdata bgrt_image_size;
+size_t bgrt_image_size;
  
  struct bmp_header {

u16 id;


--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH] x86/efi: remove pointless call to PciIo->Attributes()

2018-06-26 Thread Hans de Goede

Hi,

On 24-06-18 19:29, Ard Biesheuvel wrote:

When it was first introduced, the EFI stub code that copies the
contents of PCI option ROMs originally only intended to do so if
the EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM attribute was *not* set.

The reason was that the UEFI spec permits PCI option ROM images
to be provided by the platform directly, rather than via the ROM
BAR, and in this case, the OS can only access them at runtime if
they are preserved at boot time by copying them from the areas
described by PciIo->RomImage and PciIo->RomSize.

However, it implemented this check erroneously, as can be seen in
commit dd5fc854de5fd ("EFI: Stash ROMs if they're not in the PCI
BAR"):

 if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
 continue;

and given that the numeric value of EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
is 0x4000, this condition never becomes true, and so the option ROMs
were copied unconditionally.

This was spotted and 'fixed' by commit 886d751a2ea99a160
("x86, efi: correct precedence of operators in setup_efi_pci"),
but inadvertently inverted the logic at the same time, defeating
the purpose of the code, since it now only preserves option ROM
images that can be read from the ROM BAR as well.

Unsurprisingly, this broke some systems, and so the check was removed
entirely in commit 739701888f5d ("x86, efi: remove attribute check
from setup_efi_pci").

It is debatable whether this check should have been included in the
first place, since the option ROM image provided to the UEFI driver by
the firmware may be different from the one that is actually present in
the card's flash ROM, and so whatever PciIo->RomImage points at should
be preferred regardless of whether the attribute is set.

As this was the only use of the attributes field, we can remove
the call to PciIo->Attributes() entirely, which is especially
nice because its prototype involves uint64_t type by-value
arguments which the EFI mixed mode has trouble dealing with.

Cc: Wilfried Klaebe 
Cc: Ingo Molnar 
Cc: Thomas Gleixner 
Cc: Lukas Wunner 
Cc: Hans de Goede 
Signed-off-by: Ard Biesheuvel 



I can confirm that this fixes the mixed mode UEFI boot issues:

Tested-by: Hans de Goede 

Regards,

Hans




---

This should fix the mixed mode issue reported by Hans after my fix
for 64-bit native mode was included in v4.18-rc2.

  arch/x86/boot/compressed/eboot.c | 12 +++-
  1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index e57665b4ba1c..e98522ea6f09 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -114,18 +114,12 @@ __setup_efi_pci(efi_pci_io_protocol_t *pci, struct 
pci_setup_rom **__rom)
struct pci_setup_rom *rom = NULL;
efi_status_t status;
unsigned long size;
-   uint64_t attributes, romsize;
+   uint64_t romsize;
void *romimage;
  
-	status = efi_call_proto(efi_pci_io_protocol, attributes, pci,

-   EfiPciIoAttributeOperationGet, 0ULL,
-   );
-   if (status != EFI_SUCCESS)
-   return status;
-
/*
-* Some firmware images contain EFI function pointers at the place 
where the
-* romimage and romsize fields are supposed to be. Typically the EFI
+* Some firmware images contain EFI function pointers at the place where
+* the romimage and romsize fields are supposed to be. Typically the EFI
 * code is mapped at high addresses, translating to an unrealistically
 * large romsize. The UEFI spec limits the size of option ROMs to 16
 * MiB so we reject any ROMs over 16 MiB in size to catch this.


--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] x86/efi: Fix incorrect invocation of PciIo->Attributes()

2018-06-24 Thread Hans de Goede

Hi Ard,

On 23-06-18 23:19, Ard Biesheuvel wrote:

Commit 2c3625cb9fa2

   efi/x86: Fold __setup_efi_pci32() and __setup_efi_pci64() into one function

merged the two versions of __setup_efi_pciXX(), without taking into
account that the 32-bit version used a rather dodgy trick to pass an
immediate 0 constant as argument for a uint64_t parameter.

The issue is caused by the fact that on x86, UEFI protocol method calls
are redirected via struct efi_config::call(), which is a variadic function,
and so the compiler has to infer the types of the parameters from the
arguments rather than from the prototype. As the 32-bit x86 calling
convention passes arguments via the stack, passing the unqualified
constant 0 twice is the same as passing 0ULL, which is why the 32-bit
code in __setup_efi_pci32() contained the following call:

   status = efi_early->call(pci->attributes, pci,
EfiPciIoAttributeOperationGet, 0, 0,
);

to invoke this UEFI protocol method:

   typedef
   EFI_STATUS
   (EFIAPI *EFI_PCI_IO_PROTOCOL_ATTRIBUTES) (
 IN  EFI_PCI_IO_PROTOCOL *This,
 IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
 IN  UINT64  Attributes,
 OUT UINT64  *Result OPTIONAL
 );

After the merge, we inadvertently ended up with this version for both
32-bit and 64-bit builds, breaking the latter.

So replace the two zeroes with the explicitly typed constant 0ULL,
which works as expected on both 32-bit and 64-bit builds.

Reported-by: Wilfried Klaebe 
Tested-by: Wilfried Klaebe 
Signed-off-by: Ard Biesheuvel 
---

Wilfried tested the 64-bit build, and I checked the generated assembly
of a 32-bit build with and without this patch, and they are identical.


Ard, thank you for Cc-ing me on this.

I've tested a 64 bit kernel build on a 32 bit UEFI firmware (so mixed mode)
and this patch causes a reboot loop there. I do get grub (no surprise there
as grub is unchanged), but as soon as the kernel loads the device resets.

So I think we need some special casing there to deal with a 64 bit kernel
calling into 32 bit UEFI.

Regards,

Hans





Ingo, mind applying this directly? Thanks.

  arch/x86/boot/compressed/eboot.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index a8a8642d2b0b..e57665b4ba1c 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -118,7 +118,7 @@ __setup_efi_pci(efi_pci_io_protocol_t *pci, struct 
pci_setup_rom **__rom)
void *romimage;
  
  	status = efi_call_proto(efi_pci_io_protocol, attributes, pci,

-   EfiPciIoAttributeOperationGet, 0, 0,
+   EfiPciIoAttributeOperationGet, 0ULL,
);
if (status != EFI_SUCCESS)
return status;


--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] efi/libstub/tpm: Initialize efi_physical_addr_t vars to zero for mixed mode

2018-06-21 Thread Hans de Goede

Hi,

On 21-06-18 09:57, Ard Biesheuvel wrote:

On 21 June 2018 at 09:42, Hans de Goede  wrote:

Commit 79832f0b5f71 ("efi/libstub/tpm: Initialize pointer variables to zero
for mixed mode") fixes a problem with the tpm code on mixed mode (64 bit
kernel on 32 bit UEFI), where 64-bit pointer variables are not fully
initialized by the 32-bit EFI code.

A simlar problem applies to the efi_physical_addr_t variables which
are written by the get_event_log EFI call. Even though efi_physical_addr_t
is 64 bit everywhere it seems that some 32 bit UEFI implementations only
fill in the lower 32 bits when passed a pointer to an efi_physical_addr_t
to fill.

This commit initializes these to 0 to, to ensure the upper 32 bits are
0 in mixed mode. This fixes recent kernels sometimes hanging during
early boot on mixed mode UEFI systems.

Signed-off-by: Hans de Goede 
---
Changes in v2:
-Change commit message to reflect that efi_physical_addr_t is 64 bit
  everywhere and some firmwares only filling the lower 32 bits is somewhat
  unexpected


Thanks Hans

Queued in efi/next


Thanks,

I just realized I forgot to add a "Cc: sta...@vger.kernel.org", the problem
of some BYT machines not booting about 50% of the times was introduced
in 4.17.

Given that this is a bugfix for this, it would be good to get this added to
4.18-rc# and 4.17.x

Regards,

Hans







---
  drivers/firmware/efi/libstub/tpm.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/libstub/tpm.c 
b/drivers/firmware/efi/libstub/tpm.c
index caa37a6dd9d4..a90b0b8fc69a 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -64,7 +64,7 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t 
*sys_table_arg)
 efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
 efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
 efi_status_t status;
-   efi_physical_addr_t log_location, log_last_entry;
+   efi_physical_addr_t log_location = 0, log_last_entry = 0;
 struct linux_efi_tpm_eventlog *log_tbl = NULL;
 unsigned long first_entry_addr, last_entry_addr;
 size_t log_size, last_entry_size;
--
2.17.1


--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] efi/libstub/tpm: Initialize efi_physical_addr_t vars to zero for mixed mode

2018-06-21 Thread Hans de Goede
Commit 79832f0b5f71 ("efi/libstub/tpm: Initialize pointer variables to zero
for mixed mode") fixes a problem with the tpm code on mixed mode (64 bit
kernel on 32 bit UEFI), where 64-bit pointer variables are not fully
initialized by the 32-bit EFI code.

A simlar problem applies to the efi_physical_addr_t variables which
are written by the get_event_log EFI call. Even though efi_physical_addr_t
is 64 bit everywhere it seems that some 32 bit UEFI implementations only
fill in the lower 32 bits when passed a pointer to an efi_physical_addr_t
to fill.

This commit initializes these to 0 to, to ensure the upper 32 bits are
0 in mixed mode. This fixes recent kernels sometimes hanging during
early boot on mixed mode UEFI systems.

Signed-off-by: Hans de Goede 
---
Changes in v2:
-Change commit message to reflect that efi_physical_addr_t is 64 bit
 everywhere and some firmwares only filling the lower 32 bits is somewhat
 unexpected
---
 drivers/firmware/efi/libstub/tpm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/libstub/tpm.c 
b/drivers/firmware/efi/libstub/tpm.c
index caa37a6dd9d4..a90b0b8fc69a 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -64,7 +64,7 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t 
*sys_table_arg)
efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
efi_status_t status;
-   efi_physical_addr_t log_location, log_last_entry;
+   efi_physical_addr_t log_location = 0, log_last_entry = 0;
struct linux_efi_tpm_eventlog *log_tbl = NULL;
unsigned long first_entry_addr, last_entry_addr;
size_t log_size, last_entry_size;
-- 
2.17.1

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] efi/libstub/tpm: Initialize efi_physical_addr_t vars to zero for mixed mode

2018-06-20 Thread Hans de Goede

Hi,

On 20-06-18 09:49, Ard Biesheuvel wrote:

On 19 June 2018 at 21:50, Hans de Goede  wrote:

Commit 79832f0b5f71 ("efi/libstub/tpm: Initialize pointer variables to zero
for mixed mode") fixes a problem with the tpm code on mixed mode (64 bit
kernel on 32 bit UEFI), where 64-bit pointer variables are not fully
initialized by the 32-bit EFI code.

The same problem applies to the efi_physical_addr_t variables which
are written by the get_event_log EFI call.

This commit initializes these to 0 to, to ensure the upper 32 bits are
0 in mixed mode. This fixes recent kernels sometimes hanging during
early boot on mixed mode UEFI systems.



efi_physical_addr_t is always a 64-bit type, regardless of mixed mode,
so this smells like buggy firmware.


That is true. I would not be surprised if this is buggy firmware,
this is the infamous Insyde firmware for Bay Trail devices which
is weird and special in many ways as it was first written to bring
up Android and then modified to run Windows later (I think / it
seems). At least the DSDT tables have Android and Windows specific
bits and some firmware-s have a setup switch to select which bits
get activated, while others try to autodetect which OS they
are going to boot.

Anyways I will do a v2 with a fixed commit message taking into
account that efi_physical_addr_t is always a 64-bit type.


Is the issue 100% reproducible?


Without this change my Asus T100TA boots about once every other
time, maybe even worse like once every 3 boots.

When it does not boot most of the time it hangs in early boot
(before the efifb driver initializes), sometimes it hangs only
for a minute or 2 and then reboots.

With this change it boots 10 out 10 times, both after a power
off + wait 10 sec + on and on regular reboots.

Regards,

Hans








Signed-off-by: Hans de Goede 
---
  drivers/firmware/efi/libstub/tpm.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/libstub/tpm.c 
b/drivers/firmware/efi/libstub/tpm.c
index caa37a6dd9d4..a90b0b8fc69a 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -64,7 +64,7 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t 
*sys_table_arg)
 efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
 efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
 efi_status_t status;
-   efi_physical_addr_t log_location, log_last_entry;
+   efi_physical_addr_t log_location = 0, log_last_entry = 0;
 struct linux_efi_tpm_eventlog *log_tbl = NULL;
 unsigned long first_entry_addr, last_entry_addr;
 size_t log_size, last_entry_size;
--
2.17.1


--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] efi/libstub/tpm: Initialize efi_physical_addr_t vars to zero for mixed mode

2018-06-19 Thread Hans de Goede
Commit 79832f0b5f71 ("efi/libstub/tpm: Initialize pointer variables to zero
for mixed mode") fixes a problem with the tpm code on mixed mode (64 bit
kernel on 32 bit UEFI), where 64-bit pointer variables are not fully
initialized by the 32-bit EFI code.

The same problem applies to the efi_physical_addr_t variables which
are written by the get_event_log EFI call.

This commit initializes these to 0 to, to ensure the upper 32 bits are
0 in mixed mode. This fixes recent kernels sometimes hanging during
early boot on mixed mode UEFI systems.

Signed-off-by: Hans de Goede 
---
 drivers/firmware/efi/libstub/tpm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/libstub/tpm.c 
b/drivers/firmware/efi/libstub/tpm.c
index caa37a6dd9d4..a90b0b8fc69a 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -64,7 +64,7 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t 
*sys_table_arg)
efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
efi_status_t status;
-   efi_physical_addr_t log_location, log_last_entry;
+   efi_physical_addr_t log_location = 0, log_last_entry = 0;
struct linux_efi_tpm_eventlog *log_tbl = NULL;
unsigned long first_entry_addr, last_entry_addr;
size_t log_size, last_entry_size;
-- 
2.17.1

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/2] efifb: Copy the ACPI BGRT boot graphics to the framebuffer

2018-06-18 Thread Hans de Goede
On systems where fbcon is configured for deferred console takeover, the
intend is for the framebuffer to show the boot graphics (e.g a vendor
logo) until some message (e.g. an error) is printed or a graphical
session takes over.

Some firmware relies on the OS to show the boot graphics.

This patch adds support to efifb to show the boot graphics and
automatically enables this when fbcon is configured for deferred
console takeover.

Signed-off-by: Hans de Goede 
---
Changes in v2:
-Simplify the comment about acpi_bgrt.status
-Clear the parts of the screen which don't contain the logo to black
 (memset to 0), rather then leaving them as is
---
 drivers/video/fbdev/efifb.c | 140 
 1 file changed, 140 insertions(+)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 46a4484e3da7..fa01eecc0a55 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -9,16 +9,39 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include  /* For drm_get_panel_orientation_quirk */
 #include   /* For DRM_MODE_PANEL_ORIENTATION_* */
 
+struct bmp_file_header {
+   u16 id;
+   u32 file_size;
+   u32 reserved;
+   u32 bitmap_offset;
+} __packed;
+
+struct bmp_dib_header {
+   u32 dib_header_size;
+   s32 width;
+   s32 height;
+   u16 planes;
+   u16 bpp;
+   u32 compression;
+   u32 bitmap_size;
+   u32 horz_resolution;
+   u32 vert_resolution;
+   u32 colors_used;
+   u32 colors_important;
+} __packed;
+
 static bool request_mem_succeeded = false;
 static bool nowc = false;
 
@@ -66,6 +89,121 @@ static int efifb_setcolreg(unsigned regno, unsigned red, 
unsigned green,
return 0;
 }
 
+/*
+ * If fbcon deffered console takeover is configured, the intent is for the
+ * framebuffer to show the boot graphics (e.g. vendor logo) until there is some
+ * (error) message to display. But the boot graphics may have been destroyed by
+ * e.g. option ROM output, detect this and restore the boot graphics.
+ */
+#if defined CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER && \
+defined CONFIG_ACPI_BGRT
+static void efifb_copy_bmp(u8 *src, u32 *dst, int width, struct screen_info 
*si)
+{
+   u8 r, g, b;
+
+   while (width--) {
+   b = *src++;
+   g = *src++;
+   r = *src++;
+   *dst++ = (r << si->red_pos)   |
+(g << si->green_pos) |
+(b << si->blue_pos);
+   }
+}
+
+static void efifb_show_boot_graphics(struct fb_info *info)
+{
+   u32 bmp_width, bmp_height, bmp_pitch, screen_pitch, dst_x, y, src_y;
+   struct screen_info *si = _info;
+   struct bmp_file_header *file_header;
+   struct bmp_dib_header *dib_header;
+   void *bgrt_image = NULL;
+   u8 *dst = info->screen_base;
+
+   if (!bgrt_tab.image_address) {
+   pr_info("efifb: No BGRT, not showing boot graphics\n");
+   return;
+   }
+
+   /* Avoid flashing the logo if we're going to print std probe messages */
+   if (console_loglevel > CONSOLE_LOGLEVEL_QUIET)
+   return;
+
+   /* bgrt_tab.status is unreliable, so we don't check it */
+
+   if (si->lfb_depth != 32) {
+   pr_info("efifb: not 32 bits, not showing boot graphics\n");
+   return;
+   }
+
+   bgrt_image = memremap(bgrt_tab.image_address, bgrt_image_size,
+ MEMREMAP_WB);
+   if (!bgrt_image) {
+   pr_warn("efifb: Ignoring BGRT: failed to map image memory\n");
+   return;
+   }
+
+   if (bgrt_image_size < (sizeof(*file_header) + sizeof(*dib_header)))
+   goto error;
+
+   file_header = bgrt_image;
+   if (file_header->id != 0x4d42 || file_header->reserved != 0)
+   goto error;
+
+   dib_header = bgrt_image + sizeof(*file_header);
+   if (dib_header->dib_header_size != 40 || dib_header->width < 0 ||
+   dib_header->planes != 1 || dib_header->bpp != 24 ||
+   dib_header->compression != 0)
+   goto error;
+
+   bmp_width = dib_header->width;
+   bmp_height = abs(dib_header->height);
+   bmp_pitch = round_up(3 * bmp_width, 4);
+   screen_pitch = si->lfb_linelength;
+
+   if ((file_header->bitmap_offset + bmp_pitch * bmp_height) >
+   bgrt_image_size)
+   goto error;
+
+   if ((bgrt_tab.image_offset_x + bmp_width) > si->lfb_width ||
+   (bgrt_tab.image_offset_y + bmp_height) > si->lfb_height)
+   goto error;
+
+   pr_info("efifb: showing boot graphics\n");
+
+   for (y = 0; y < si->lfb_height; y++, dst += si->lfb_linelength) {
+

[PATCH v2 1/2] efi/bgrt: Drop __initdata from bgrt_image_size

2018-06-18 Thread Hans de Goede
bgrt_image_size is necessary to (optionally) show the boot graphics from
the efifb code. The efifb driver is a platform driver, using a normal
driver probe() driver callback. So even though it is always builtin it
cannot reference __initdata.

Acked-by: Ard Biesheuvel 
Signed-off-by: Hans de Goede 
---
 drivers/firmware/efi/efi-bgrt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/efi-bgrt.c b/drivers/firmware/efi/efi-bgrt.c
index 50793fda7819..b22ccfb0c991 100644
--- a/drivers/firmware/efi/efi-bgrt.c
+++ b/drivers/firmware/efi/efi-bgrt.c
@@ -20,7 +20,7 @@
 #include 
 
 struct acpi_table_bgrt bgrt_tab;
-size_t __initdata bgrt_image_size;
+size_t bgrt_image_size;
 
 struct bmp_header {
u16 id;
-- 
2.17.1

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/2] efifb: Copy the ACPI BGRT boot graphics to the

2018-06-18 Thread Hans de Goede

Hi,

On 18-06-18 11:23, Daniel Vetter wrote:

On Sun, Jun 17, 2018 at 05:32:33PM +0200, Hans de Goede wrote:

Hi All,

Here is a patch-set to make sure that the efifb contains the boot
graphics from the ACPI BGRT extension when the kernel is configured
to use the (new) deferred fbcon console takeover support.

Let me explain why this is desirable (same reason as for the deferred
fbcon console takeover support itself):

Various (desktop oriented) Linux distributions have spend a lot of time
to not show way too technial boot messages to end users during bootup.
What we would really like for the boot experience is something like
MacOS X / Windows 10 do. The (EFI) firmware boots up a logo and we
leave that in place until the login-manager (e.g. gdm) starts and then
the login-manager takes over the framebuffer including the current logo
contents and fades that into the login screen.

The deferred fbcon console takeover (combined with shim and grub)
patches makes the desired boot experience possible, but this assumes
that the firmware starts shim with the framebuffer containing the
boot graphics. This is not always the case, this patch ensures that the
boot graphics are in place.

Since the bgrt.status field is not exactly reliable, this commit simply
always copies over the bootgraphics. If they are already there this
effectively is a no-op.

The first patch in this series makes a trivial change to
drivers/firmware/efi/efi-bgrt.c, dropping __initdata from bgrt_image_size.

Ard, since the second patch depends on the first and the change is
really trivial, can we please have your ack for merging the efi-bgrt.c
change through the fbdev tree?


Random side-comment ... plans to roll out the same for drm drivers? With
the client infrastructure Noralf is working on doing that should be fairly
straight-forward. Interim step would be to add it to the shared fbdev
emulation layer (but that's a bit a hack, and precludes the use of this on
fbcon-less systems).


I had not really thought about this yet.

AFAICT the ACPI BGRT table is part of UEFI, so having it also means
having an UEFI framebuffer and I expect us to always use that to be
able to show error messages initializing the real drm/kms driver.

But I guess in the future the plan it to stop using the efifb
linux driver and instead use simple drm, then we will certainly
want this in drm.

And thinking more about this, currently I'm relying (for a
flickerfree experience) on the kms driver taking over the fb
setup by the firmware.  But I guess it may not always succeed and
if it does not succeed, then restoring the bootgraphics
(on a quiet boot) would be good too.

Once I've everything upstream to make flickerfree work for i915 I plan
to look at the amd / nouveau cases next. For those adding BGRT graphics
restoration to the drm drivers might make for a good quick fix. We
would still get a flicker from the modeset but at least the screen
would not be just black until the gui loads if we restore the boot
graphics from the drm driver and I guess we could prime the fb with
the bootgraphics before the modeset to make the flicker as small
as possible.

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] efifb: Copy the ACPI BGRT boot graphics to the framebuffer

2018-06-18 Thread Hans de Goede

Hi,

On 18-06-18 10:43, Ard Biesheuvel wrote:

On 18 June 2018 at 10:30, Hans de Goede  wrote:

Hi,

On 18-06-18 09:36, Ard Biesheuvel wrote:


Hallo Hans,

On 17 June 2018 at 17:32, Hans de Goede  wrote:


On systems where fbcon is configured for deferred console takeover, the
intend is for the framebuffer to show the boot graphics (e.g a vendor
logo) until some message (e.g. an error) is printed or a graphical
session takes over.

Some firmware however relies on the OS to show the boot graphics
(indicated by bgrt_tab.status being 0) and the boot graphics may have
been destroyed by e.g. the grub boot menu.

This patch adds support to efifb to show the boot graphics and
automatically enables this when fbcon is configured for deferred
console takeover.

Signed-off-by: Hans de Goede 



I have tested this code on ARM QEMU/mach-virt, and with a little tweak
(which I will post separately), the code works as expected, i.e., it
redraws the boot logo based on the contents of the BGRT table.



That is great.


However, what it doesn't do is clear the screen, which means the logo
is drawn on top of whatever the boot environment left behind, and I
end up with something like this.

http://people.linaro.org/~ard.biesheuvel/mach-virt-bgrt-logo-redrawn.png



Hmm, less great. I'm not sure how to deal with this, on x86 it is more
or less guaranteed that the screen is already cleared when we load and
clearing a 4k screen means writing about 32MB, which I guess with modern
RAM speeds is not that bad actually.

I see that you got this picture by manual booting from the EFI shell,
in what state does the firmware / bootloader normally leave the
framebuffer?


UEFI does not usually clear the screen when it boots the default
entry, so it is entirely dependent on the boot loader that runs next.
I guess GRUB usually clears the screen unconditionally?


It depends, GRUB either leaves it completely alone (leaving the
BGRT graphics which the firmware hopefully has put up already
in place) or if it actually draws anything, then it clears iit
before starting the kernel.


In any case, I think it is reasonable to clear the screen if you
redraw the logo, but I do wonder if it is safe to assume that the
background color is black.

Instead, we may decide to clear the screen before ExitBootServices()
[using EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen()].


On most x86 machines (but not all, GRR) the firmware itself will
draw the logo already. I actually have grub patches pending to make
it not do any text-output related calls at all unless it actually
has a message / menu it wants to display.

Calling EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen() will cause
a bootup sequence like this:

firmware draws logo
clearscreen
redraw logo

Which will cause an ugly flash to black. Where as the purpose
is to have a smooth boot with the logo being on screen all
the time without any flickers / flashes.

I've never seen a machine where the background is not black,
the background not being black would also break the spinning
dots which microsofts draws on top of the background while
booting, so a memset to 0 seems sensible to me.


  I'm asking because if normally it is either cleared
to black, or already showing the logo I wonder if we should take the
(small) penalty of clearing ?

Given that we are talking about only 32 MB I could do a v2 which just
memsets the rest of the screen to 0.

So we get:

 for (y= 0; y < height; y++) {
 if (line_part_of_bgrt) {
 memset(left-of-bgrt);
 draw_bgrt_line(y);
 memset(right-of-bgrt);
 } else {
 memset(line);
 }
 }

Note I've deliberately done the if on a per line
base to keep the actual blit part of the loop
efficient and without any extra conditionals in
there. I also don't simply first memset the entire
fb to 0 to avoid a flash / tearing if the bgrt
image is already in place (which happens often on
x86).

Implementing this is easy and as said the extra execution time should
be quite small, still I wonder what others think about this?

I'm leaning towards doing the clearing / memsets since I've seen
some firmwares leave some artifacts from not completely clearing
things like a "Press F2 to enter setup" message, missing a few
pixels and leaving those on screen.



I think the overhead of doing the clearing is not going to be the
bottleneck. But redrawing a logo on black background that was designed
to be displayed over another color is going to look really ugly ...


Do you know of any examples of this ?

There seems to be no known way to get the background color, so black /
all 0 seems the be the best bet.

I would expect any non black background logos to simply be screen
filling.

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More 

Re: [PATCH 2/2] efifb: Copy the ACPI BGRT boot graphics to the framebuffer

2018-06-18 Thread Hans de Goede

Hi,

On 18-06-18 09:36, Ard Biesheuvel wrote:

Hallo Hans,

On 17 June 2018 at 17:32, Hans de Goede  wrote:

On systems where fbcon is configured for deferred console takeover, the
intend is for the framebuffer to show the boot graphics (e.g a vendor
logo) until some message (e.g. an error) is printed or a graphical
session takes over.

Some firmware however relies on the OS to show the boot graphics
(indicated by bgrt_tab.status being 0) and the boot graphics may have
been destroyed by e.g. the grub boot menu.

This patch adds support to efifb to show the boot graphics and
automatically enables this when fbcon is configured for deferred
console takeover.

Signed-off-by: Hans de Goede 


I have tested this code on ARM QEMU/mach-virt, and with a little tweak
(which I will post separately), the code works as expected, i.e., it
redraws the boot logo based on the contents of the BGRT table.


That is great.


However, what it doesn't do is clear the screen, which means the logo
is drawn on top of whatever the boot environment left behind, and I
end up with something like this.

http://people.linaro.org/~ard.biesheuvel/mach-virt-bgrt-logo-redrawn.png


Hmm, less great. I'm not sure how to deal with this, on x86 it is more
or less guaranteed that the screen is already cleared when we load and
clearing a 4k screen means writing about 32MB, which I guess with modern
RAM speeds is not that bad actually.

I see that you got this picture by manual booting from the EFI shell,
in what state does the firmware / bootloader normally leave the
framebuffer?  I'm asking because if normally it is either cleared
to black, or already showing the logo I wonder if we should take the
(small) penalty of clearing ?

Given that we are talking about only 32 MB I could do a v2 which just
memsets the rest of the screen to 0.

So we get:

for (y= 0; y < height; y++) {
if (line_part_of_bgrt) {
memset(left-of-bgrt);
draw_bgrt_line(y);
memset(right-of-bgrt);
} else {
memset(line);
}
}

Note I've deliberately done the if on a per line
base to keep the actual blit part of the loop
efficient and without any extra conditionals in
there. I also don't simply first memset the entire
fb to 0 to avoid a flash / tearing if the bgrt
image is already in place (which happens often on
x86).

Implementing this is easy and as said the extra execution time should
be quite small, still I wonder what others think about this?

I'm leaning towards doing the clearing / memsets since I've seen
some firmwares leave some artifacts from not completely clearing
things like a "Press F2 to enter setup" message, missing a few
pixels and leaving those on screen.

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] efifb: Copy the ACPI BGRT boot graphics to the framebuffer

2018-06-18 Thread Hans de Goede

Hi,

On 18-06-18 10:53, Môshe van der Sterre wrote:

Hi Hans,

On 06/17/2018 05:32 PM, Hans de Goede wrote:

On systems where fbcon is configured for deferred console takeover, the
intend is for the framebuffer to show the boot graphics (e.g a vendor
logo) until some message (e.g. an error) is printed or a graphical
session takes over.

Some firmware however relies on the OS to show the boot graphics
(indicated by bgrt_tab.status being 0) and the boot graphics may have
been destroyed by e.g. the grub boot menu.


It may be clearer to just say that the boot graphics may have been destroyed. 
The reference to the status field and firmware expectations only confuses the 
intention of this patch, imho.
(This ties in to what I say below)


This patch adds support to efifb to show the boot graphics and
automatically enables this when fbcon is configured for deferred
console takeover.

+   /*
+* We do not check bgrt_tab.status here because this seems to only
+* reflect if the firmware has shown the boot graphics at all, if it
+* later got destroyed by something status will still be 1.
+* Since we draw the exact same graphic at the exact same place this
+* will not lead to any tearing if the boot graphic is already there.
+*/


I agree that ignoring bgrt_tab.status is the absolute best option.

The status (valid-bit) can, in the real world, be any value with any meaning.
I checked this on a few machines as part of commit 66dbe99cfe30.
  - My workstation always has 0.
  - An old server that I checked always has 1.
  - My laptop has 1 if the boot is uninterrupted, 0 if I request the UEFI boot 
menu.

So, I have the same reservation about this comment as I have about the commit 
message. Imho, simply mentioning that the status field cannot be relied upon 
(in any case), would get the point across.


Ok, I will simplify both the commit message and comment bits to just state
that the status field is unreliable.

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/2] efifb: Copy the ACPI BGRT boot graphics to the

2018-06-17 Thread Hans de Goede
Hi All,

Here is a patch-set to make sure that the efifb contains the boot
graphics from the ACPI BGRT extension when the kernel is configured
to use the (new) deferred fbcon console takeover support.

Let me explain why this is desirable (same reason as for the deferred
fbcon console takeover support itself):

Various (desktop oriented) Linux distributions have spend a lot of time
to not show way too technial boot messages to end users during bootup.
What we would really like for the boot experience is something like
MacOS X / Windows 10 do. The (EFI) firmware boots up a logo and we
leave that in place until the login-manager (e.g. gdm) starts and then
the login-manager takes over the framebuffer including the current logo
contents and fades that into the login screen.

The deferred fbcon console takeover (combined with shim and grub)
patches makes the desired boot experience possible, but this assumes
that the firmware starts shim with the framebuffer containing the
boot graphics. This is not always the case, this patch ensures that the
boot graphics are in place.

Since the bgrt.status field is not exactly reliable, this commit simply
always copies over the bootgraphics. If they are already there this
effectively is a no-op.

The first patch in this series makes a trivial change to
drivers/firmware/efi/efi-bgrt.c, dropping __initdata from bgrt_image_size.

Ard, since the second patch depends on the first and the change is
really trivial, can we please have your ack for merging the efi-bgrt.c
change through the fbdev tree?

Regards,

Hans

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] efi/bgrt: Drop __initdata from bgrt_image_size

2018-06-17 Thread Hans de Goede
bgrt_image_size is necessary to (optionally) show the boot graphics from
the efifb code. The efifb driver is a platform driver, using a normal
driver probe() driver callback. So even though it is always builtin it
cannot reference __initdata.

Signed-off-by: Hans de Goede 
---
 drivers/firmware/efi/efi-bgrt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/efi-bgrt.c b/drivers/firmware/efi/efi-bgrt.c
index 50793fda7819..b22ccfb0c991 100644
--- a/drivers/firmware/efi/efi-bgrt.c
+++ b/drivers/firmware/efi/efi-bgrt.c
@@ -20,7 +20,7 @@
 #include 
 
 struct acpi_table_bgrt bgrt_tab;
-size_t __initdata bgrt_image_size;
+size_t bgrt_image_size;
 
 struct bmp_header {
u16 id;
-- 
2.17.1

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] efifb: Copy the ACPI BGRT boot graphics to the framebuffer

2018-06-17 Thread Hans de Goede
On systems where fbcon is configured for deferred console takeover, the
intend is for the framebuffer to show the boot graphics (e.g a vendor
logo) until some message (e.g. an error) is printed or a graphical
session takes over.

Some firmware however relies on the OS to show the boot graphics
(indicated by bgrt_tab.status being 0) and the boot graphics may have
been destroyed by e.g. the grub boot menu.

This patch adds support to efifb to show the boot graphics and
automatically enables this when fbcon is configured for deferred
console takeover.

Signed-off-by: Hans de Goede 
---
 drivers/video/fbdev/efifb.c | 147 
 1 file changed, 147 insertions(+)

diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 46a4484e3da7..b041d936a438 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -9,16 +9,39 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include  /* For drm_get_panel_orientation_quirk */
 #include   /* For DRM_MODE_PANEL_ORIENTATION_* */
 
+struct bmp_file_header {
+   u16 id;
+   u32 file_size;
+   u32 reserved;
+   u32 bitmap_offset;
+} __packed;
+
+struct bmp_dib_header {
+   u32 dib_header_size;
+   s32 width;
+   s32 height;
+   u16 planes;
+   u16 bpp;
+   u32 compression;
+   u32 bitmap_size;
+   u32 horz_resolution;
+   u32 vert_resolution;
+   u32 colors_used;
+   u32 colors_important;
+} __packed;
+
 static bool request_mem_succeeded = false;
 static bool nowc = false;
 
@@ -66,6 +89,128 @@ static int efifb_setcolreg(unsigned regno, unsigned red, 
unsigned green,
return 0;
 }
 
+/*
+ * If fbcon deffered console takeover is configured, the intent is for the
+ * framebuffer to show the boot graphics (e.g. vendor logo) until there is some
+ * (error) message to display. But the boot graphics may have been destroyed by
+ * e.g. option ROM output, detect this and restore the boot graphics.
+ */
+#if defined CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER && \
+defined CONFIG_ACPI_BGRT
+static void efifb_show_boot_graphics(struct fb_info *info)
+{
+   u32 *dst, bmp_width, bmp_height, bmp_pitch, screen_pitch;
+   struct screen_info *si = _info;
+   struct bmp_file_header *file_header;
+   struct bmp_dib_header *dib_header;
+   void *bgrt_image = NULL;
+   u8 *src, r, g, b;
+   s32 x, y;
+
+   if (!bgrt_tab.image_address) {
+   pr_info("efifb: No BGRT, not showing boot graphics\n");
+   return;
+   }
+
+   /* Avoid flashing the logo if we're going to print std probe messages */
+   if (console_loglevel > CONSOLE_LOGLEVEL_QUIET)
+   return;
+
+   /*
+* We do not check bgrt_tab.status here because this seems to only
+* reflect if the firmware has shown the boot graphics at all, if it
+* later got destroyed by something status will still be 1.
+* Since we draw the exact same graphic at the exact same place this
+* will not lead to any tearing if the boot graphic is already there.
+*/
+
+   if (si->lfb_depth != 32) {
+   pr_info("efifb: not 32 bits, not showing boot graphics\n");
+   return;
+   }
+
+   bgrt_image = memremap(bgrt_tab.image_address, bgrt_image_size,
+ MEMREMAP_WB);
+   if (!bgrt_image) {
+   pr_warn("efifb: Ignoring BGRT: failed to map image memory\n");
+   return;
+   }
+
+   if (bgrt_image_size < (sizeof(*file_header) + sizeof(*dib_header)))
+   goto error;
+
+   file_header = bgrt_image;
+   if (file_header->id != 0x4d42 || file_header->reserved != 0)
+   goto error;
+
+   dib_header = bgrt_image + sizeof(*file_header);
+   if (dib_header->dib_header_size != 40 || dib_header->width < 0 ||
+   dib_header->planes != 1 || dib_header->bpp != 24 ||
+   dib_header->compression != 0)
+   goto error;
+
+   bmp_width = dib_header->width;
+   bmp_height = abs(dib_header->height);
+   bmp_pitch = round_up(3 * bmp_width, 4);
+   screen_pitch = si->lfb_linelength;
+
+   if ((file_header->bitmap_offset + bmp_pitch * bmp_height) >
+   bgrt_image_size)
+   goto error;
+
+   if ((bgrt_tab.image_offset_x + bmp_width) > si->lfb_width ||
+   (bgrt_tab.image_offset_y + bmp_height) > si->lfb_height)
+   goto error;
+
+   pr_info("efifb: showing boot graphics\n");
+
+   src = bgrt_image + file_header->bitmap_offset;
+   bmp_pitch -= 3 * bmp_width;
+   if (dib_header->height < 0) {
+   for (y = 0; y < bmp_height; y++) {
+   dst = (

Re: [PATCH v6 2/5] efi: Add embedded peripheral firmware support

2018-06-07 Thread Hans de Goede

Hi,

On 06-06-18 23:42, Luis R. Rodriguez wrote:

On Wed, Jun 06, 2018 at 08:39:15PM +0200, Hans de Goede wrote:

On 05-06-18 23:07, Luis R. Rodriguez wrote:

+To make request_firmware() fallback to trying EFI embedded firmwares after 
this,
+the driver must set a boolean "efi-embedded-firmware" device-property on the
+device before passing it to request_firmware().


No, as I have requested before I don't want this, it is silly to have such
functionality always be considered as a fallback if we only have 2 drivers
which need this. > Please add a call which only if used would then *evaluate*
such fallback prospect.


Ok, so I've a few questions about this:

1) You want me to add a:

int firmware_request_with_system_firmware_fallback(struct device *device, const 
char *name);

function?


The idea is correct, the name however is obviously terrible.

This is functionality that is very specialized and only *two* device drivers
need it that we are aware of which would be upstream. Experience has shown
fallback mechanisms *can* be a pain, and if we add this we will be supporting
this for *life*, as such I'd very much prefer to:

a) *Clearly* reduce the scope of functionality clearly *beyond* what you
have done.

b) Have access to one simple call which folks can use to *clearly* and
quickly grep for those oddball drivers using this new interface.

We can do this by using a separate function for it.

Before you claim something seems unreasonable from the above logic, please read
the latest state of affairs with respect to data driven Vs functional API
evolution discussion over the firmware API [0] as well as my latests
recommendation for what to do for the async firmware API [1].

The skinny of it is that long ago I actually proposed having only *two*
firmware API calls, an async and a sync call and having all functionality
fleshed out through a structure of parameters. The issue with that strategy was
it was *too* data driven, and as per Greg's request we'll instead be exposing
new symbols per functionality for the firmware API with his justification
that this is just what is traditionally done on Linux. Hence we have
firmware_request_nowarn() now for just a slight variation for a sync call.

Despite Greg's recommendation -- for the respective async functionality I
suggested this is not going to scale well -- it is also just dumb to follow the
same approach there for a few reasons.

1) We have only *one* async call and had decided to *not* provide a structure
for that call since its inception

2) Over time have evolved this single async call each time we have a new 
feature,
causing a slew of collateral evolutions.

So, while we like it or not, it turns out the async call to the firmware API
is already completely data driven. Extending it with just another argument
would just be silly now.

So refer to my recommendations to Andres for how to evolve the async API if
you need it, however from a quick review you don't need async calls, so you
won't have to address any of that.

[0] https://lkml.kernel.org/r/20180421173650.gw14...@wotan.suse.de
[1] https://lkml.kernel.org/r/20180422202609.gx14...@wotan.suse.de


Note I've deliberately named it with_system_firmware_fallback
and not with_efi_fallback to have the name be platform agnostic in
case we want something similar on other platforms in the future.


firmware_request_platform() ?


And then have this pass a new FW_OPT_SYS_FW_FALLBACK flag to
_request_firmware(), right ?


Yeap.


2) Should this flag then be checked inside _request_firmware() before it
calls fw_get_efi_embedded_fw() (which may be an empty stub),


You are the architect behind this call, so its up to you.

To answer this you have to review the other flags and see if other users of the
other flags may want your functionality. For instance the Android folks for
instance rely on the FW_OPT_NOFALLBACK - the sysfs fallback mechanism to
account for odd partition layouts. Could they ever want to use your fallback
mechanism? Granted your mechanism is for x86, but they could eventually add
support for it on ARM.

Checking if the firmware is on the EFI platform firmware list is much faster
than the fallback mechanism, that would be one gain for them, as such it may
make sense to check for firmware_request_platform() before using the sysfs
fallback mechanism.  However if Android folks want to always override the
platform firmware with the sysfs fallback interface we'd need another flag
added and call to then change the order later if we checked for for the
platform firmware first.


I believe we agreed a while back that the platform fallback would
replace the sysfs one when requested. I believe that still makes
sense. If a driver wants both it can simply call request_firmware_foo
itself twice and determine the order itself.


If you however are 100% sure they won't need it, than checking
firmware_request_platform() first would make sense now if you are
certain these same devic

Re: [PATCH v6 2/5] efi: Add embedded peripheral firmware support

2018-06-06 Thread Hans de Goede

Hi,

On 05-06-18 23:07, Luis R. Rodriguez wrote:

On Fri, Jun 01, 2018 at 02:53:27PM +0200, Hans de Goede wrote:

Just like with PCI options ROMs, which we save in the setup_efi_pci*
functions from arch/x86/boot/compressed/eboot.c, the EFI code / ROM itself
sometimes may contain data which is useful/necessary for peripheral drivers
to have access to.

Specifically the EFI code may contain an embedded copy of firmware which
needs to be (re)loaded into the peripheral. Normally such firmware would be
part of linux-firmware, but in some cases this is not feasible, for 2
reasons:

1) The firmware is customized for a specific use-case of the chipset / use
with a specific hardware model, so we cannot have a single firmware file
for the chipset. E.g. touchscreen controller firmwares are compiled
specifically for the hardware model they are used with, as they are
calibrated for a specific model digitizer.

2) Despite repeated attempts we have failed to get permission to
redistribute the firmware. This is especially a problem with customized
firmwares, these get created by the chip vendor for a specific ODM and the
copyright may partially belong with the ODM, so the chip vendor cannot
give a blanket permission to distribute these.

This commit adds support for finding peripheral firmware embedded in the
EFI code and making this available to peripheral drivers through the
standard firmware loading mechanism.

Note we check the EFI_BOOT_SERVICES_CODE for embedded firmware near the end
of start_kernel(), just before calling rest_init(), this is on purpose
because the typical EFI_BOOT_SERVICES_CODE memory-segment is too large for
early_memremap(), so the check must be done after mm_init(). This relies
on EFI_BOOT_SERVICES_CODE not being free-ed until efi_free_boot_services()
is called, which means that this will only work on x86 for now.

Reported-by: Dave Olsthoorn 
Suggested-by: Peter Jones 
Acked-by: Ard Biesheuvel 
Signed-off-by: Hans de Goede 
---
Changes in v6:
-Rework code to remove casts from if (prefix == mem) comparison
-Use SHA256 hashes instead of crc32 sums
-Add new READING_FIRMWARE_EFI_EMBEDDED read_file_id and use it
-Call security_kernel_read_file(NULL, READING_FIRMWARE_EFI_EMBEDDED)
  to check if this is allowed before looking at EFI embedded fw
-Document why we are not using the PI Firmware Volume protocol

Changes in v5:
-Rename the EFI_BOOT_SERVICES flag to EFI_PRESERVE_BS_REGIONS

Changes in v4:
-Drop note in docs about EFI_FIRMWARE_VOLUME_PROTOCOL, it is not part of
  UEFI proper, so the EFI maintainers don't want us referring people to it
-Use new EFI_BOOT_SERVICES flag
-Put the new fw_get_efi_embedded_fw() function in its own fallback_efi.c
  file which only gets built when EFI_EMBEDDED_FIRMWARE is selected
-Define an empty stub for fw_get_efi_embedded_fw() in fallback.h hwen
  EFI_EMBEDDED_FIRMWARE is not selected, to avoid the need for #ifdefs
  in firmware_loader/main.c
-Properly call security_kernel_post_read_file() on the firmware returned
  by efi_get_embedded_fw() to make sure that we are allowed to use it

Changes in v3:
-Fix the docs using "efi-embedded-fw" as property name instead of
  "efi-embedded-firmware"

Changes in v2:
-Rebased on driver-core/driver-core-next
-Add documentation describing the EFI embedded firmware mechanism to:
  Documentation/driver-api/firmware/request_firmware.rst
-Add a new EFI_EMBEDDED_FIRMWARE Kconfig bool and only build the embedded
  fw support if this is set. This is an invisible option which should be
  selected by drivers which need this
-Remove the efi_embedded_fw_desc and dmi_system_id-s for known devices
  from the efi-embedded-fw code, instead drivers using this are expected to
  export a dmi_system_id array, with each entries' driver_data pointing to a
  efi_embedded_fw_desc struct and register this with the efi-embedded-fw code
-Use kmemdup to make a copy instead of efi_mem_reserve()-ing the firmware,
  this avoids us messing with the EFI memmap and avoids the need to make
  changes to efi_mem_desc_lookup()
-Make the firmware-loader code only fallback to efi_get_embedded_fw() if the
  passed in device has the "efi-embedded-firmware" device-property bool set
-Skip usermodehelper fallback when "efi-embedded-firmware" device-property
  is set
---
  .../driver-api/firmware/request_firmware.rst  |  76 +
  drivers/base/firmware_loader/Makefile |   1 +
  drivers/base/firmware_loader/fallback.h   |  12 ++
  drivers/base/firmware_loader/fallback_efi.c   |  56 +++
  drivers/base/firmware_loader/main.c   |   2 +
  drivers/firmware/efi/Kconfig  |   3 +
  drivers/firmware/efi/Makefile |   1 +
  drivers/firmware/efi/embedded-firmware.c  | 148 ++
  include/linux/efi.h   |   6 +
  include/linux/efi_embedded_fw.h   |  25 +++
  include/linux/fs.h|   1 +
  init/main.c   

Re: [PATCH v6 0/5] efi/firmware/platform-x86: Add EFI embedded fw support

2018-06-06 Thread Hans de Goede

Hi,

On 05-06-18 22:46, Luis R. Rodriguez wrote:

On Fri, Jun 01, 2018 at 02:53:25PM +0200, Hans de Goede wrote:

Hi All,

Here is v6 of my patch-set to add support for EFI embedded fw to the kernel.

This patch-set applies on top of the "[PATCH v7 00/14] firmware_loader
changes for v4.18" series from mcgrof.

It now also depends on the series from Andy Lutomirski which allow using the
sha256 code in a standalone manner. Andy what is the status of those?

Changes since v5:
-Rework code to remove casts from if (prefix == mem) comparison
-Use SHA256 hashes instead of crc32 sums


Nice! I see no updates on this progress, but it would seem this
may then mean this cannot be merged until the release after?


Once the sha256 bits are in place the subsys tree which has them
merged can create an immutable branch for Greg to merge and
then these can be applied on top of that merge.

But yes this means that these probably won't go in for another
cycle or 2, that is fine.


-Add new READING_FIRMWARE_EFI_EMBEDDED read_file_id and use it
-Call security_kernel_read_file(NULL, READING_FIRMWARE_EFI_EMBEDDED)
  to check if this is allowed before looking at EFI embedded fw


There's a discussion over having security_kernel_read_file(NULL,
READING_WHATEVER) become another LSM hook. So your series would conflict with
that at the moment.

So yet another piece of code which this series depends on.


Ah well, I'm in no big hurry to get this merged. OTOH if this is
ready and that discussion is not yet finished it might be better
to merge this as is and then have the security_kernel_read_file / LSM
hook series fix this up as necessary when it is merged.

Regards,

Hans






-Document why we are not using the PI Firmware Volume protocol

For reference I've included the coverletter from v4 (which includes
previous covverletters) below.

Regards,

Hans


Previous coverletter:

Here is v5 of my patch-set to add support for EFI embedded fw to the kernel.

Changes since v4:
-Rename the EFI_BOOT_SERVICES flag to EFI_PRESERVE_BS_REGIONS

So I think this patch-set is getting close to ready for merging, which
brings us to the question of how to merge this, I think that patches 1
and 2 should probably both be merged through the same tree. Then an
unmutable branch should be created on that tree, merged into the
platform/x86 tree and then the last 3 patches can be merged through
that tree.

Ard has already indicated he is fine with the EFI bits going upstream
through another tree, so perhaps patches 1-2 can be merged through the
firmware-loader-tree and then do an unmutable branch on the
firmware-loader-tree for the platform/x86 tree to merge?

I don't think taking all 5 through 1 tree is a good idea because of
the file rename under platform/x86.


For the record here are the cover letters of the previous versions:

Changes since v3:
-Drop note in docs about EFI_FIRMWARE_VOLUME_PROTOCOL, it is not part of
  UEFI proper, so the EFI maintainers don't want us referring people to it
-Use new EFI_BOOT_SERVICES flag
-Put the new fw_get_efi_embedded_fw() function in its own fallback_efi.c
  file which only gets built when EFI_EMBEDDED_FIRMWARE is selected
-Define an empty stub for fw_get_efi_embedded_fw() in fallback.h hwen
  EFI_EMBEDDED_FIRMWARE is not selected, to avoid the need for #ifdefs
  in firmware_loader/main.c
-Properly call security_kernel_post_read_file() on the firmware returned
  by efi_get_embedded_fw() to make sure that we are allowed to use it

The 3 most prominent changes in v2 are:

1) Add documentation describing the EFI embedded firmware mechanism to:
Documentation/driver-api/firmware/request_firmware.rst

2) Instead of having a single dmi_system_id array with its driver_data
members pointing to efi_embedded_fw_desc structs, have the drivers which
need EFI embedded-fw support export a dmi_system_id array and register
that with the EFI embedded-fw code

This series also includes the first driver to use this, in the form of
the touchscreen_dmi code (formerly silead_dmi) from drivers/platfrom/x86

3) As discussed during the review of v1 we want to make the firmware_loader
code fallback to EFI embedded-fw optional.  Rather the adding yet another
firmware_request_foo variant for this, with the risk of later also needing
firmware_request_foo_nowait, etc. variants I've decided to make the code
check if the device has a "efi-embedded-firmware" device-property bool set.

This also seemed better because the same driver may want to use the
fallback on some systems, but not on others since e.g. not all (x86)
systems with a silead touchscreen have their touchscreen firmware embedded
in their EFI.

Note that (as discussed) when the EFI fallback path is requested, the
usermodehelper fallback path is skipped.

Here is the full changelog of patch 2/5 which is where most of the changes are:

Changes in v2:
-Rebased on driver-core/driver-core-next
-Add docu

[PATCH v6 3/5] platform/x86: Rename silead_dmi to touchscreen_dmi

2018-06-01 Thread Hans de Goede
Not only silead touchscreens need some extra info not available in the
ACPI tables to work properly. X86 devices with a Chipone ICN8505 chip also
need some DMI based extra configuration.

There is no reason to have separate dmi config code per touchscreen
controller vendor. This commit renames silead_dmi to a more generic
touchscreen_dmi name (and Kconfig option) in preparation of adding
info for tablets with an ICN8505 based touchscreen.

Note there are no functional changes all code changes are limited to
removing references to silead where these are no longer applicable.

Acked-by: Andy Shevchenko 
Acked-by: Ard Biesheuvel 
Signed-off-by: Hans de Goede 
---
 MAINTAINERS   |  2 +-
 drivers/platform/x86/Kconfig  | 16 ++---
 drivers/platform/x86/Makefile |  2 +-
 .../x86/{silead_dmi.c => touchscreen_dmi.c}   | 72 +--
 4 files changed, 46 insertions(+), 46 deletions(-)
 rename drivers/platform/x86/{silead_dmi.c => touchscreen_dmi.c} (88%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9474e9834dc7..6b02f2b9814d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12775,7 +12775,7 @@ L:  linux-in...@vger.kernel.org
 L: platform-driver-...@vger.kernel.org
 S: Maintained
 F: drivers/input/touchscreen/silead.c
-F: drivers/platform/x86/silead_dmi.c
+F: drivers/platform/x86/touchscreen_dmi.c
 
 SILICON MOTION SM712 FRAME BUFFER DRIVER
 M: Sudip Mukherjee 
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 566644bb496a..d4e9670ee8cc 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1196,16 +1196,16 @@ config INTEL_TURBO_MAX_3
  This driver is only required when the system is not using Hardware
  P-States (HWP). In HWP mode, priority can be read from ACPI tables.
 
-config SILEAD_DMI
-   bool "Tablets with Silead touchscreens"
+config TOUCHSCREEN_DMI
+   bool "DMI based touchscreen configuration info"
depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD
---help---
- Certain ACPI based tablets with Silead touchscreens do not have
- enough data in ACPI tables for the touchscreen driver to handle
- the touchscreen properly, as OEMs expected the data to be baked
- into the tablet model specific version of the driver shipped
- with the OS-image for the device. This option supplies the missing
- information. Enable this for x86 tablets with Silead touchscreens.
+ Certain ACPI based tablets with e.g. Silead or Chipone touchscreens
+ do not have enough data in ACPI tables for the touchscreen driver to
+ handle the touchscreen properly, as OEMs expect the data to be baked
+ into the tablet model specific version of the driver shipped with the
+ the OS-image for the device. This option supplies the missing info.
+ Enable this for x86 tablets with Silead or Chipone touchscreens.
 
 config INTEL_CHTDC_TI_PWRBTN
tristate "Intel Cherry Trail Dollar Cove TI power button driver"
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 2ba6cb795338..8d9477114fb5 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -78,7 +78,7 @@ obj-$(CONFIG_INTEL_SMARTCONNECT)  += intel-smartconnect.o
 obj-$(CONFIG_PVPANIC)   += pvpanic.o
 obj-$(CONFIG_ALIENWARE_WMI)+= alienware-wmi.o
 obj-$(CONFIG_INTEL_PMC_IPC)+= intel_pmc_ipc.o
-obj-$(CONFIG_SILEAD_DMI)   += silead_dmi.o
+obj-$(CONFIG_TOUCHSCREEN_DMI)  += touchscreen_dmi.o
 obj-$(CONFIG_SURFACE_PRO3_BUTTON)  += surfacepro3_button.o
 obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o
 obj-$(CONFIG_INTEL_PUNIT_IPC)  += intel_punit_ipc.o
diff --git a/drivers/platform/x86/silead_dmi.c 
b/drivers/platform/x86/touchscreen_dmi.c
similarity index 88%
rename from drivers/platform/x86/silead_dmi.c
rename to drivers/platform/x86/touchscreen_dmi.c
index 853a7ce4601c..8fb489e1e16c 100644
--- a/drivers/platform/x86/silead_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -1,5 +1,5 @@
 /*
- * Silead touchscreen driver DMI based configuration code
+ * Touchscreen driver DMI based configuration code
  *
  * Copyright (c) 2017 Red Hat Inc.
  *
@@ -20,7 +20,7 @@
 #include 
 #include 
 
-struct silead_ts_dmi_data {
+struct ts_dmi_data {
const char *acpi_name;
const struct property_entry *properties;
 };
@@ -34,7 +34,7 @@ static const struct property_entry cube_iwork8_air_props[] = {
{ }
 };
 
-static const struct silead_ts_dmi_data cube_iwork8_air_data = {
+static const struct ts_dmi_data cube_iwork8_air_data = {
.acpi_name  = "MSSL1680:00",
.properties = cube_iwork8_air_props,
 };
@@ -48,7 +48,7 @@ static const struct property_entry jumper_ezpad_mini3_props[] 
= {
{ }
 };
 
-static const struct silead_ts

[PATCH v6 1/5] efi: Export boot-services code and data as debugfs-blobs

2018-06-01 Thread Hans de Goede
Sometimes it is useful to be able to dump the efi boot-services code and
data. This commit adds these as debugfs-blobs to /sys/kernel/debug/efi,
but only if efi=debug is passed on the kernel-commandline as this requires
not freeing those memory-regions, which costs 20+ MB of RAM.

Reviewed-by: Greg Kroah-Hartman 
Acked-by: Ard Biesheuvel 
Signed-off-by: Hans de Goede 
---
Changes in v5:
-Rename the EFI_BOOT_SERVICES flag to EFI_PRESERVE_BS_REGIONS

Changes in v4:
-Add new EFI_BOOT_SERVICES flag and use it to determine if the boot-services
 memory segments are available (and thus if it makes sense to register the
 debugfs bits for them)

Changes in v2:
-Do not call pr_err on debugfs call failures
---
 arch/x86/platform/efi/efi.c|  1 +
 arch/x86/platform/efi/quirks.c |  4 +++
 drivers/firmware/efi/efi.c | 53 ++
 include/linux/efi.h|  1 +
 4 files changed, 59 insertions(+)

diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 9061babfbc83..82f0836d 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -208,6 +208,7 @@ int __init efi_memblock_x86_reserve_range(void)
 efi.memmap.desc_version);
 
memblock_reserve(pmap, efi.memmap.nr_map * efi.memmap.desc_size);
+   set_bit(EFI_PRESERVE_BS_REGIONS, );
 
return 0;
 }
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 36c1f8b9f7e0..16bdb9e3b343 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -376,6 +376,10 @@ void __init efi_free_boot_services(void)
int num_entries = 0;
void *new, *new_md;
 
+   /* Keep all regions for /sys/kernel/debug/efi */
+   if (efi_enabled(EFI_DBG))
+   return;
+
for_each_efi_memory_desc(md) {
unsigned long long start = md->phys_addr;
unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 232f4915223b..1590e4d6a857 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -325,6 +326,55 @@ static __init int efivar_ssdt_load(void)
 static inline int efivar_ssdt_load(void) { return 0; }
 #endif
 
+#ifdef CONFIG_DEBUG_FS
+
+#define EFI_DEBUGFS_MAX_BLOBS 32
+
+static struct debugfs_blob_wrapper debugfs_blob[EFI_DEBUGFS_MAX_BLOBS];
+
+static void __init efi_debugfs_init(void)
+{
+   struct dentry *efi_debugfs;
+   efi_memory_desc_t *md;
+   char name[32];
+   int type_count[EFI_BOOT_SERVICES_DATA + 1] = {};
+   int i = 0;
+
+   efi_debugfs = debugfs_create_dir("efi", NULL);
+   if (IS_ERR_OR_NULL(efi_debugfs))
+   return;
+
+   for_each_efi_memory_desc(md) {
+   switch (md->type) {
+   case EFI_BOOT_SERVICES_CODE:
+   snprintf(name, sizeof(name), "boot_services_code%d",
+type_count[md->type]++);
+   break;
+   case EFI_BOOT_SERVICES_DATA:
+   snprintf(name, sizeof(name), "boot_services_data%d",
+type_count[md->type]++);
+   break;
+   default:
+   continue;
+   }
+
+   debugfs_blob[i].size = md->num_pages << EFI_PAGE_SHIFT;
+   debugfs_blob[i].data = memremap(md->phys_addr,
+   debugfs_blob[i].size,
+   MEMREMAP_WB);
+   if (!debugfs_blob[i].data)
+   continue;
+
+   debugfs_create_blob(name, 0400, efi_debugfs, _blob[i]);
+   i++;
+   if (i == EFI_DEBUGFS_MAX_BLOBS)
+   break;
+   }
+}
+#else
+static inline void efi_debugfs_init(void) {}
+#endif
+
 /*
  * We register the efi subsystem with the firmware subsystem and the
  * efivars subsystem with the efi subsystem, if the system was booted with
@@ -369,6 +419,9 @@ static int __init efisubsys_init(void)
goto err_remove_group;
}
 
+   if (efi_enabled(EFI_DBG) && efi_enabled(EFI_PRESERVE_BS_REGIONS))
+   efi_debugfs_init();
+
return 0;
 
 err_remove_group:
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 56add823f190..d72358e892e7 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1144,6 +1144,7 @@ extern int __init efi_setup_pcdp_console(char *);
 #define EFI_DBG8   /* Print additional debug info 
at runtime */
 #define EFI_NX_PE_DATA 9   /* Can runtime data regions be mapped 
non-executable? */
 #define EFI_MEM_ATTR   10  /* Did firmware publish an 
EFI_MEMORY_ATTRIBUTES ta

[PATCH v6 2/5] efi: Add embedded peripheral firmware support

2018-06-01 Thread Hans de Goede
Just like with PCI options ROMs, which we save in the setup_efi_pci*
functions from arch/x86/boot/compressed/eboot.c, the EFI code / ROM itself
sometimes may contain data which is useful/necessary for peripheral drivers
to have access to.

Specifically the EFI code may contain an embedded copy of firmware which
needs to be (re)loaded into the peripheral. Normally such firmware would be
part of linux-firmware, but in some cases this is not feasible, for 2
reasons:

1) The firmware is customized for a specific use-case of the chipset / use
with a specific hardware model, so we cannot have a single firmware file
for the chipset. E.g. touchscreen controller firmwares are compiled
specifically for the hardware model they are used with, as they are
calibrated for a specific model digitizer.

2) Despite repeated attempts we have failed to get permission to
redistribute the firmware. This is especially a problem with customized
firmwares, these get created by the chip vendor for a specific ODM and the
copyright may partially belong with the ODM, so the chip vendor cannot
give a blanket permission to distribute these.

This commit adds support for finding peripheral firmware embedded in the
EFI code and making this available to peripheral drivers through the
standard firmware loading mechanism.

Note we check the EFI_BOOT_SERVICES_CODE for embedded firmware near the end
of start_kernel(), just before calling rest_init(), this is on purpose
because the typical EFI_BOOT_SERVICES_CODE memory-segment is too large for
early_memremap(), so the check must be done after mm_init(). This relies
on EFI_BOOT_SERVICES_CODE not being free-ed until efi_free_boot_services()
is called, which means that this will only work on x86 for now.

Reported-by: Dave Olsthoorn 
Suggested-by: Peter Jones 
Acked-by: Ard Biesheuvel 
Signed-off-by: Hans de Goede 
---
Changes in v6:
-Rework code to remove casts from if (prefix == mem) comparison
-Use SHA256 hashes instead of crc32 sums
-Add new READING_FIRMWARE_EFI_EMBEDDED read_file_id and use it
-Call security_kernel_read_file(NULL, READING_FIRMWARE_EFI_EMBEDDED)
 to check if this is allowed before looking at EFI embedded fw
-Document why we are not using the PI Firmware Volume protocol

Changes in v5:
-Rename the EFI_BOOT_SERVICES flag to EFI_PRESERVE_BS_REGIONS

Changes in v4:
-Drop note in docs about EFI_FIRMWARE_VOLUME_PROTOCOL, it is not part of
 UEFI proper, so the EFI maintainers don't want us referring people to it
-Use new EFI_BOOT_SERVICES flag
-Put the new fw_get_efi_embedded_fw() function in its own fallback_efi.c
 file which only gets built when EFI_EMBEDDED_FIRMWARE is selected
-Define an empty stub for fw_get_efi_embedded_fw() in fallback.h hwen
 EFI_EMBEDDED_FIRMWARE is not selected, to avoid the need for #ifdefs
 in firmware_loader/main.c
-Properly call security_kernel_post_read_file() on the firmware returned
 by efi_get_embedded_fw() to make sure that we are allowed to use it

Changes in v3:
-Fix the docs using "efi-embedded-fw" as property name instead of
 "efi-embedded-firmware"

Changes in v2:
-Rebased on driver-core/driver-core-next
-Add documentation describing the EFI embedded firmware mechanism to:
 Documentation/driver-api/firmware/request_firmware.rst
-Add a new EFI_EMBEDDED_FIRMWARE Kconfig bool and only build the embedded
 fw support if this is set. This is an invisible option which should be
 selected by drivers which need this
-Remove the efi_embedded_fw_desc and dmi_system_id-s for known devices
 from the efi-embedded-fw code, instead drivers using this are expected to
 export a dmi_system_id array, with each entries' driver_data pointing to a
 efi_embedded_fw_desc struct and register this with the efi-embedded-fw code
-Use kmemdup to make a copy instead of efi_mem_reserve()-ing the firmware,
 this avoids us messing with the EFI memmap and avoids the need to make
 changes to efi_mem_desc_lookup()
-Make the firmware-loader code only fallback to efi_get_embedded_fw() if the
 passed in device has the "efi-embedded-firmware" device-property bool set
-Skip usermodehelper fallback when "efi-embedded-firmware" device-property
 is set
---
 .../driver-api/firmware/request_firmware.rst  |  76 +
 drivers/base/firmware_loader/Makefile |   1 +
 drivers/base/firmware_loader/fallback.h   |  12 ++
 drivers/base/firmware_loader/fallback_efi.c   |  56 +++
 drivers/base/firmware_loader/main.c   |   2 +
 drivers/firmware/efi/Kconfig  |   3 +
 drivers/firmware/efi/Makefile |   1 +
 drivers/firmware/efi/embedded-firmware.c  | 148 ++
 include/linux/efi.h   |   6 +
 include/linux/efi_embedded_fw.h   |  25 +++
 include/linux/fs.h|   1 +
 init/main.c   |   3 +
 12 files changed, 334 insertions(+)
 create mode 100644 drivers/base/firmware_loader/fallback_efi.c
 create m

[PATCH v6 5/5] platform/x86: touchscreen_dmi: Add info for the Chuwi Vi8 Plus tablet

2018-06-01 Thread Hans de Goede
Add touchscreen info for the Chuwi Vi8 Plus tablet. This tablet uses a
Chipone ICN8505 touchscreen controller, with the firmware used by the
touchscreen embedded in the EFI firmware.

Acked-by: Andy Shevchenko 
Acked-by: Ard Biesheuvel 
Signed-off-by: Hans de Goede 
---
Changes in v6:
-Switch from crc sums to SHA256 hashes for the firmware hash
---
 drivers/platform/x86/touchscreen_dmi.c | 28 ++
 1 file changed, 28 insertions(+)

diff --git a/drivers/platform/x86/touchscreen_dmi.c 
b/drivers/platform/x86/touchscreen_dmi.c
index 8eb88bfcacbe..99eb73bbd1a0 100644
--- a/drivers/platform/x86/touchscreen_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -359,6 +359,25 @@ static const struct ts_dmi_data onda_v891w_v1_data = {
.properties = onda_v891w_v1_props,
 };
 
+static const struct property_entry efi_embedded_fw_props[] = {
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
+   { }
+};
+
+static const struct ts_dmi_data chuwi_vi8_plus_data = {
+   .embedded_fw = {
+   .name   = "chipone/icn8505-HAMP0002.fw",
+   .prefix = { 0xb0, 0x07, 0x00, 0x00, 0xe4, 0x07, 0x00, 0x00 },
+   .length = 35012,
+   .sha256 = { 0x93, 0xe5, 0x49, 0xe0, 0xb6, 0xa2, 0xb4, 0xb3,
+   0x88, 0x96, 0x34, 0x97, 0x5e, 0xa8, 0x13, 0x78,
+   0x72, 0x98, 0xb8, 0x29, 0xeb, 0x5c, 0xa7, 0xf1,
+   0x25, 0x13, 0x43, 0xf4, 0x30, 0x7c, 0xfc, 0x7c },
+   },
+   .acpi_name  = "CHPN0001:00",
+   .properties = efi_embedded_fw_props,
+};
+
 const struct dmi_system_id touchscreen_dmi_table[] = {
{
/* CUBE iwork8 Air */
@@ -587,6 +606,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
DMI_EXACT_MATCH(DMI_BIOS_VERSION, "ONDA.W89EBBN08"),
},
},
+   {
+   /* Chuwi Vi8 Plus (CWI506) */
+   .driver_data = (void *)_vi8_plus_data,
+   .matches = {
+   DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
+   DMI_MATCH(DMI_PRODUCT_NAME, "D2D3_Vi8A1"),
+   DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+   },
+   },
{ },
 };
 
-- 
2.17.0

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 4/5] platform/x86: touchscreen_dmi: Add EFI embedded firmware info support

2018-06-01 Thread Hans de Goede
Sofar we have been unable to get permission from the vendors to put the
firmware for touchscreens listed in touchscreen_dmi in linux-firmware.

Some of the tablets with such a touchscreen have a touchscreen driver, and
thus a copy of the firmware, as part of their EFI code.

This commit adds the necessary info for the new EFI embedded-firmware code
to extract these firmwares, making the touchscreen work OOTB without the
user needing to manually add the firmware.

Acked-by: Andy Shevchenko 
Acked-by: Ard Biesheuvel 
Signed-off-by: Hans de Goede 
---
Changes in v6:
-Switch from crc sums to SHA256 hashes for the firmware hashes
---
 drivers/firmware/efi/embedded-firmware.c |  3 ++
 drivers/platform/x86/Kconfig |  1 +
 drivers/platform/x86/touchscreen_dmi.c   | 35 +++-
 include/linux/efi_embedded_fw.h  |  2 ++
 4 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/embedded-firmware.c 
b/drivers/firmware/efi/embedded-firmware.c
index 244465a162c5..19168b83cd06 100644
--- a/drivers/firmware/efi/embedded-firmware.c
+++ b/drivers/firmware/efi/embedded-firmware.c
@@ -23,6 +23,9 @@ struct embedded_fw {
 static LIST_HEAD(found_fw_list);
 
 static const struct dmi_system_id * const embedded_fw_table[] = {
+#ifdef CONFIG_TOUCHSCREEN_DMI
+   touchscreen_dmi_table,
+#endif
NULL
 };
 
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index d4e9670ee8cc..8c2082c8a7fd 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1199,6 +1199,7 @@ config INTEL_TURBO_MAX_3
 config TOUCHSCREEN_DMI
bool "DMI based touchscreen configuration info"
depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD
+   select EFI_EMBEDDED_FIRMWARE if EFI
---help---
  Certain ACPI based tablets with e.g. Silead or Chipone touchscreens
  do not have enough data in ACPI tables for the touchscreen driver to
diff --git a/drivers/platform/x86/touchscreen_dmi.c 
b/drivers/platform/x86/touchscreen_dmi.c
index 8fb489e1e16c..8eb88bfcacbe 100644
--- a/drivers/platform/x86/touchscreen_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -15,12 +15,15 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 
 struct ts_dmi_data {
+   /* The EFI embedded-fw code expects this to be the first member! */
+   struct efi_embedded_fw_desc embedded_fw;
const char *acpi_name;
const struct property_entry *properties;
 };
@@ -31,10 +34,20 @@ static const struct property_entry cube_iwork8_air_props[] 
= {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
{ }
 };
 
 static const struct ts_dmi_data cube_iwork8_air_data = {
+   .embedded_fw = {
+   .name   = "silead/gsl3670-cube-iwork8-air.fw",
+   .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+   .length = 38808,
+   .sha256 = { 0xff, 0x62, 0x2d, 0xd1, 0x8a, 0x78, 0x04, 0x7b,
+   0x33, 0x06, 0xb0, 0x4f, 0x7f, 0x02, 0x08, 0x9c,
+   0x96, 0xd4, 0x9f, 0x04, 0xe1, 0x47, 0x25, 0x25,
+   0x60, 0x77, 0x41, 0x33, 0xeb, 0x12, 0x82, 0xfc },
+   },
.acpi_name  = "MSSL1680:00",
.properties = cube_iwork8_air_props,
 };
@@ -133,10 +146,20 @@ static const struct property_entry pipo_w2s_props[] = {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name",
  "gsl1680-pipo-w2s.fw"),
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
{ }
 };
 
 static const struct ts_dmi_data pipo_w2s_data = {
+   .embedded_fw = {
+   .name   = "silead/gsl1680-pipo-w2s.fw",
+   .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+   .length = 39072,
+   .sha256 = { 0xd0, 0x58, 0xc4, 0x7d, 0x55, 0x2d, 0x62, 0x18,
+   0xd1, 0x6a, 0x71, 0x73, 0x0b, 0x3f, 0xbe, 0x60,
+   0xbb, 0x45, 0x8c, 0x52, 0x27, 0xb7, 0x18, 0xf4,
+   0x31, 0x00, 0x6a, 0x49, 0x76, 0xd8, 0x7c, 0xd3 },
+   },
.acpi_name  = "MSSL1680:00",
.properties = pipo_w2s_props,
 };
@@ -194,10 +217,20 @@ static const struct property_entry chuwi_hi8_pro_props[] 
= {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"),
PROPERTY_ENTRY_BOOL("silead,home-button"),
+  

[PATCH v6 0/5] efi/firmware/platform-x86: Add EFI embedded fw support

2018-06-01 Thread Hans de Goede
Hi All,

Here is v6 of my patch-set to add support for EFI embedded fw to the kernel.

This patch-set applies on top of the "[PATCH v7 00/14] firmware_loader
changes for v4.18" series from mcgrof.

It now also depends on the series from Andy Lutomirski which allow using the
sha256 code in a standalone manner. Andy what is the status of those?

Changes since v5:
-Rework code to remove casts from if (prefix == mem) comparison
-Use SHA256 hashes instead of crc32 sums
-Add new READING_FIRMWARE_EFI_EMBEDDED read_file_id and use it
-Call security_kernel_read_file(NULL, READING_FIRMWARE_EFI_EMBEDDED)
 to check if this is allowed before looking at EFI embedded fw
-Document why we are not using the PI Firmware Volume protocol

For reference I've included the coverletter from v4 (which includes
previous covverletters) below.

Regards,

Hans


Previous coverletter:

Here is v5 of my patch-set to add support for EFI embedded fw to the kernel.

Changes since v4:
-Rename the EFI_BOOT_SERVICES flag to EFI_PRESERVE_BS_REGIONS

So I think this patch-set is getting close to ready for merging, which
brings us to the question of how to merge this, I think that patches 1
and 2 should probably both be merged through the same tree. Then an
unmutable branch should be created on that tree, merged into the
platform/x86 tree and then the last 3 patches can be merged through
that tree.

Ard has already indicated he is fine with the EFI bits going upstream
through another tree, so perhaps patches 1-2 can be merged through the
firmware-loader-tree and then do an unmutable branch on the
firmware-loader-tree for the platform/x86 tree to merge?

I don't think taking all 5 through 1 tree is a good idea because of
the file rename under platform/x86.


For the record here are the cover letters of the previous versions:

Changes since v3:
-Drop note in docs about EFI_FIRMWARE_VOLUME_PROTOCOL, it is not part of
 UEFI proper, so the EFI maintainers don't want us referring people to it
-Use new EFI_BOOT_SERVICES flag
-Put the new fw_get_efi_embedded_fw() function in its own fallback_efi.c
 file which only gets built when EFI_EMBEDDED_FIRMWARE is selected
-Define an empty stub for fw_get_efi_embedded_fw() in fallback.h hwen
 EFI_EMBEDDED_FIRMWARE is not selected, to avoid the need for #ifdefs
 in firmware_loader/main.c
-Properly call security_kernel_post_read_file() on the firmware returned
 by efi_get_embedded_fw() to make sure that we are allowed to use it

The 3 most prominent changes in v2 are:

1) Add documentation describing the EFI embedded firmware mechanism to:
   Documentation/driver-api/firmware/request_firmware.rst

2) Instead of having a single dmi_system_id array with its driver_data
   members pointing to efi_embedded_fw_desc structs, have the drivers which
   need EFI embedded-fw support export a dmi_system_id array and register
   that with the EFI embedded-fw code

   This series also includes the first driver to use this, in the form of
   the touchscreen_dmi code (formerly silead_dmi) from drivers/platfrom/x86

3) As discussed during the review of v1 we want to make the firmware_loader
   code fallback to EFI embedded-fw optional.  Rather the adding yet another
   firmware_request_foo variant for this, with the risk of later also needing
   firmware_request_foo_nowait, etc. variants I've decided to make the code
   check if the device has a "efi-embedded-firmware" device-property bool set.

   This also seemed better because the same driver may want to use the
   fallback on some systems, but not on others since e.g. not all (x86)
   systems with a silead touchscreen have their touchscreen firmware embedded
   in their EFI.

   Note that (as discussed) when the EFI fallback path is requested, the
   usermodehelper fallback path is skipped.

Here is the full changelog of patch 2/5 which is where most of the changes are:

Changes in v2:
-Rebased on driver-core/driver-core-next
-Add documentation describing the EFI embedded firmware mechanism to:
 Documentation/driver-api/firmware/request_firmware.rst
-Add a new EFI_EMBEDDED_FIRMWARE Kconfig bool and only build the embedded
 fw support if this is set. This is an invisible option which should be
 selected by drivers which need this
-Remove the efi_embedded_fw_desc and dmi_system_id-s for known devices
 from the efi-embedded-fw code, instead drivers using this are expected to
 export a dmi_system_id array, with each entries' driver_data pointing to a
 efi_embedded_fw_desc struct and register this with the efi-embedded-fw code
-Use kmemdup to make a copy instead of efi_mem_reserve()-ing the firmware,
 this avoids us messing with the EFI memmap and avoids the need to make
 changes to efi_mem_desc_lookup()
-Make the firmware-loader code only fallback to efi_get_embedded_fw() if the
 passed in device has the "efi-embedded-firmware" device-property bool set
-Skip usermodehelper fallback when "efi-embedded-firmware" device-property
 is set

Patches 3-5 are new and implement using the 

Re: [PATCH v5 2/5] efi: Add embedded peripheral firmware support

2018-05-13 Thread Hans de Goede

Hi,

On 05/08/2018 06:12 PM, Luis R. Rodriguez wrote:

On Fri, May 04, 2018 at 07:54:28AM +0200, Ard Biesheuvel wrote:

On 4 May 2018 at 01:29, Luis R. Rodriguez <mcg...@kernel.org> wrote:

On Sun, Apr 29, 2018 at 11:35:55AM +0200, Hans de Goede wrote:

[...]

diff --git a/Documentation/driver-api/firmware/request_firmware.rst 
b/Documentation/driver-api/firmware/request_firmware.rst
index c8bddbdcfd10..560dfed76e38 100644
--- a/Documentation/driver-api/firmware/request_firmware.rst
+++ b/Documentation/driver-api/firmware/request_firmware.rst
@@ -73,3 +73,69 @@ If something went wrong firmware_request() returns non-zero 
and fw_entry
  is set to NULL. Once your driver is done with processing the firmware it
  can call call firmware_release(fw_entry) to release the firmware image
  and any related resource.
+
+EFI embedded firmware support
+=


This is a new fallback mechanism, please see:

Documentation/driver-api/firmware/fallback-mechanisms.rst

Refer to the section "Types of fallback mechanisms", augument the list there
and then move the section "Firmware sysfs loading facility" to a new file, and
then add a new file for your own.


+
+On some devices the system's EFI code / ROM may contain an embedded copy
+of firmware for some of the system's integrated peripheral devices and
+the peripheral's Linux device-driver needs to access this firmware.


You in no way indicate this is a just an invented scheme, a custom solution and
nothing standard.  I realize Ard criticized that the EFI Firmware Volume 
Protocol
is not part of the UEFI spec -- however it is a bit more widely used right?
Why can't Linux support it instead?



Most implementations of UEFI are based on PI,


That seems to be the UEFI Platform Initialization specification:

http://www.uefi.org/sites/default/files/resources/PI_Spec_1_6.pdf


and so it is likely that
the protocols are available. However, the PI spec does not cover
firmware blobs,


Indeed, I cannot find anything about it on the PI Spec, but I *can* easily
find a few documents referring to the Firmware Volume Protocol:

http://wiki.phoenix.com/wiki/index.php/EFI_FIRMWARE_VOLUME_PROTOCOL

But this has no references at all...

I see stupid patents over some of this and authentication mechanisms for it:

https://patents.google.com/patent/US20170098084


and so it is undefined whether such blobs are self
contained (i.e., in separate files in the firmware volume), statically
linked into the driver or maybe even encrypted or otherwise
encapsulated, and the actual loadable image only lives in memory.


Got it, thanks this helps! There are two things then:

  1) The "EFI Firmware Volume Protocol" ("FV" for short in your descriptions
 below), and whether to support it or not in the future and recommend it
 for future use cases.

  b) Han's EFI scraper to help support 2 drivers, and whether or not to
 recommend it for future use cases.


Hans's case is the second one, i.e., the firmware is at an arbitrary
offset in the driver image. Using the FV protocol in this case would
result in a mix of both approaches: look up the driver file by GUID
[which could change btw between different versions of the system
firmware, although this is unlikely] and then still use the prefix/crc
based approach to sift through the image itself.


Got it. And to be clear its a reversed engineered solution to what
two vendors decided to do.


But my main objection is simply that from the UEFI forum point of
view, there is a clear distinction between the OS visible interfaces
in the UEFI spec and the internal interfaces in the PI spec (which for
instance are not subject to the same rules when it comes to backward
compatibility), and so I think we should not depend on PI at all.


Ah I see.


This
is all the more important considering that we are trying to encourage
the creation of other implementations of UEFI that are not based on PI
(e.g., uboot for arm64 implements the required UEFI interfaces for
booting the kernel via GRUB), and adding dependencies on PI protocols
makes that a moving target.


Got it!


So in my view, we either take a ad-hoc approach which works for the
few platforms we expect to support, in which case Hans's approach is
sufficient,


Modulo it needs some work for ARM as it only works for x86 right now ;)


or we architect it properly, in which case we shouldn't
depend on PI because it does not belong in a properly architected
OS<->firmware exchange.


OK, it sounds to me like we have room to then implement our own de-facto
standard for letting vendors stuff firmware into EFI as we in the Linux
community see fit.

We can start out by supporting existing drivers, but also consider customizing
this in the future for our own needs, so long as we document it and set
expectations well.

So we need to support what Hans is implementing for two reasons then:

a) The FV Protocol cannot be used to support the two

Re: [PATCH v5 2/5] efi: Add embedded peripheral firmware support

2018-05-13 Thread Hans de Goede

Hi,

On 05/13/2018 12:43 PM, Ard Biesheuvel wrote:

On 13 May 2018 at 13:03, Hans de Goede <hdego...@redhat.com> wrote:

Hi,


On 05/04/2018 06:56 AM, Ard Biesheuvel wrote:


Hi Hans,

One comment below, which I missed in review before.

On 29 April 2018 at 11:35, Hans de Goede <hdego...@redhat.com> wrote:


Just like with PCI options ROMs, which we save in the setup_efi_pci*
functions from arch/x86/boot/compressed/eboot.c, the EFI code / ROM
itself
sometimes may contain data which is useful/necessary for peripheral
drivers
to have access to.

Specifically the EFI code may contain an embedded copy of firmware which
needs to be (re)loaded into the peripheral. Normally such firmware would
be
part of linux-firmware, but in some cases this is not feasible, for 2
reasons:

1) The firmware is customized for a specific use-case of the chipset /
use
with a specific hardware model, so we cannot have a single firmware file
for the chipset. E.g. touchscreen controller firmwares are compiled
specifically for the hardware model they are used with, as they are
calibrated for a specific model digitizer.

2) Despite repeated attempts we have failed to get permission to
redistribute the firmware. This is especially a problem with customized
firmwares, these get created by the chip vendor for a specific ODM and
the
copyright may partially belong with the ODM, so the chip vendor cannot
give a blanket permission to distribute these.

This commit adds support for finding peripheral firmware embedded in the
EFI code and making this available to peripheral drivers through the
standard firmware loading mechanism.

Note we check the EFI_BOOT_SERVICES_CODE for embedded firmware near the
end
of start_kernel(), just before calling rest_init(), this is on purpose
because the typical EFI_BOOT_SERVICES_CODE memory-segment is too large
for
early_memremap(), so the check must be done after mm_init(). This relies
on EFI_BOOT_SERVICES_CODE not being free-ed until
efi_free_boot_services()
is called, which means that this will only work on x86 for now.

Reported-by: Dave Olsthoorn <d...@bewaar.me>
Suggested-by: Peter Jones <pjo...@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheu...@linaro.org>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---


[...]


diff --git a/drivers/firmware/efi/embedded-firmware.c
b/drivers/firmware/efi/embedded-firmware.c
new file mode 100644
index ..22a0f598b53d
--- /dev/null
+++ b/drivers/firmware/efi/embedded-firmware.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Support for extracting embedded firmware for peripherals from EFI
code,
+ *
+ * Copyright (c) 2018 Hans de Goede <hdego...@redhat.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct embedded_fw {
+   struct list_head list;
+   const char *name;
+   void *data;
+   size_t length;
+};
+
+static LIST_HEAD(found_fw_list);
+
+static const struct dmi_system_id * const embedded_fw_table[] = {
+   NULL
+};
+
+/*
+ * Note the efi_check_for_embedded_firmwares() code currently makes the
+ * following 2 assumptions. This may needs to be revisited if embedded
firmware
+ * is found where this is not true:
+ * 1) The firmware is only found in EFI_BOOT_SERVICES_CODE memory
segments
+ * 2) The firmware always starts at an offset which is a multiple of 8
bytes
+ */
+static int __init efi_check_md_for_embedded_firmware(
+   efi_memory_desc_t *md, const struct efi_embedded_fw_desc *desc)
+{
+   struct embedded_fw *fw;
+   u64 i, size;
+   u32 crc;
+   u8 *mem;
+
+   size = md->num_pages << EFI_PAGE_SHIFT;
+   mem = memremap(md->phys_addr, size, MEMREMAP_WB);
+   if (!mem) {
+   pr_err("Error mapping EFI mem at %#llx\n",
md->phys_addr);
+   return -ENOMEM;
+   }
+
+   size -= desc->length;
+   for (i = 0; i < size; i += 8) {
+   if (*((u64 *)(mem + i)) != *((u64 *)desc->prefix))
+   continue;
+



Please use the proper APIs here to cast u8* to u64*, i.e., either use
get_unaligned64() or use memcmp()



But we know the memory addresses are 64 bit aligned, so using
get_unaligned64 seems wrong, and I'm not sure if the compiler is
smart enough to optimize a memcmp to the single 64 bit integer comparison
we want done here.



Fair enough. The memory regions are indeed guaranteed to be 4k aligned.

So in that case, please make mem a u64* and cast the other way where needed.


Ok, I've reworked the code to get rid of the compares in the if condition.

Regards,

Hans








+   /* Seed with ~0, invert to match crc32 userspace utility
*/
+   crc = ~crc32(~0, mem + i, desc->length);
+   if (crc == desc->crc)
+   break;
+   }
+
+   memunmap(mem);
+
+   if (i >= size)
+   return -ENOENT;
+
+   pr_info("Found E

Re: [PATCH v5 2/5] efi: Add embedded peripheral firmware support

2018-05-13 Thread Hans de Goede

Hi,

On 05/03/2018 11:35 PM, Andy Lutomirski wrote:

On Thu, May 3, 2018 at 3:31 PM Luis R. Rodriguez <mcg...@kernel.org> wrote:


On Wed, May 02, 2018 at 04:49:53PM +0200, Hans de Goede wrote:

Hi,

On 05/01/2018 09:29 PM, Andy Lutomirski wrote:

On Sun, Apr 29, 2018 at 2:36 AM Hans de Goede <hdego...@redhat.com>

wrote:

+The EFI embedded-fw code works by scanning all

EFI_BOOT_SERVICES_CODE

memory

+segments for an eight byte sequence matching prefix, if the prefix

is

found it

+then does a crc32 over length bytes and if that matches makes a

copy of

length

+bytes and adds that to its list with found firmwares.
+


Eww, gross.  Is there really no better way to do this?


I'm afraid not.


  Is the issue that
the EFI code does not intend to pass the firmware to the OS but that

it has

a copy for its own purposes and that Linux is just going to hijack

EFI's

copy?  If so, that's brilliant and terrible at the same time.


Yes that is exactly the issue / what it happening here.




+   for (i = 0; i < size; i += 8) {
+   if (*((u64 *)(mem + i)) != *((u64 *)desc->prefix))
+   continue;
+
+   /* Seed with ~0, invert to match crc32 userspace

utility

*/

+   crc = ~crc32(~0, mem + i, desc->length);
+   if (crc == desc->crc)
+   break;
+   }


I hate to play the security card, but this stinks a bit.  The kernel
obviously needs to trust the EFI boot services code since the EFI boot
services code is free to modify the kernel image.  But your patch is

not

actually getting this firmware blob from the boot services code via

any

defined interface -- you're literally snarfing up the blob from a

range of

memory.  I fully expect there to be any number of ways for

untrustworthy

entities to inject malicious blobs into this memory range on quite a

few

implementations.  For example, there are probably unauthenticated EFI
variables and even parts of USB sticks and such that get read into

boot

services memory, and I see no reason at all to expect that nothing in

the

so-called "boot services code" range is actually just plain old boot
services *heap*.

Fortunately, given your design, this is very easy to fix.  Just

replace

CRC32 with SHA-256 or similar.  If you find the crypto api too ugly

for

this purpose, I have patches that only need a small amount of dusting

off

to give an entirely reasonable SHA-256 API in the kernel.


My main reason for going with crc32 is that the scanning happens before
the kernel is fully up and running (it happens just before the

rest_init()

call in start_kernel() (from init/main.c) I'm open to using the
crypto api, but I was not sure if that is ready for use at that time.



Not being sure is different than being certain. As Andy noted, if that

does

not work please poke Andy about the SHA-256 API he has which would enable
its use in kernel.


Nah, don't use the cryptoapi for this.  You'll probably regret it for any
number of reasons.  My code is here:

https://git.kernel.org/pub/scm/linux/kernel/git/luto/linux.git/commit/?h=crypto/sha256_bpf=e9e12f056f2abed50a30b762db9185799f5864e6

and its two parents.  It needs a little bit of dusting and it needs
checking that all combinations of modular and non-modular builds work.  Ard
probably has further comments.


Looks good, I've cherry picked this into my personal tree and will make
the next version of the EFI embedded-firmware patches use SHA256.

As Luis already mentioned geting the EFI embedded-firmware patches
upstream is not something urgent, so it is probably best to just
wait for you to push these upstream I guess?

Regards,

Hans

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v5 2/5] efi: Add embedded peripheral firmware support

2018-05-13 Thread Hans de Goede

Hi,

On 05/03/2018 11:31 PM, Luis R. Rodriguez wrote:

On Wed, May 02, 2018 at 04:49:53PM +0200, Hans de Goede wrote:

Hi,

On 05/01/2018 09:29 PM, Andy Lutomirski wrote:

On Sun, Apr 29, 2018 at 2:36 AM Hans de Goede <hdego...@redhat.com> wrote:

+The EFI embedded-fw code works by scanning all EFI_BOOT_SERVICES_CODE

memory

+segments for an eight byte sequence matching prefix, if the prefix is

found it

+then does a crc32 over length bytes and if that matches makes a copy of

length

+bytes and adds that to its list with found firmwares.
+


Eww, gross.  Is there really no better way to do this?


I'm afraid not.


  Is the issue that
the EFI code does not intend to pass the firmware to the OS but that it has
a copy for its own purposes and that Linux is just going to hijack EFI's
copy?  If so, that's brilliant and terrible at the same time.


Yes that is exactly the issue / what it happening here.




+   for (i = 0; i < size; i += 8) {
+   if (*((u64 *)(mem + i)) != *((u64 *)desc->prefix))
+   continue;
+
+   /* Seed with ~0, invert to match crc32 userspace utility

*/

+   crc = ~crc32(~0, mem + i, desc->length);
+   if (crc == desc->crc)
+   break;
+   }


I hate to play the security card, but this stinks a bit.  The kernel
obviously needs to trust the EFI boot services code since the EFI boot
services code is free to modify the kernel image.  But your patch is not
actually getting this firmware blob from the boot services code via any
defined interface -- you're literally snarfing up the blob from a range of
memory.  I fully expect there to be any number of ways for untrustworthy
entities to inject malicious blobs into this memory range on quite a few
implementations.  For example, there are probably unauthenticated EFI
variables and even parts of USB sticks and such that get read into boot
services memory, and I see no reason at all to expect that nothing in the
so-called "boot services code" range is actually just plain old boot
services *heap*.

Fortunately, given your design, this is very easy to fix.  Just replace
CRC32 with SHA-256 or similar.  If you find the crypto api too ugly for
this purpose, I have patches that only need a small amount of dusting off
to give an entirely reasonable SHA-256 API in the kernel.


My main reason for going with crc32 is that the scanning happens before
the kernel is fully up and running (it happens just before the rest_init()
call in start_kernel() (from init/main.c) I'm open to using the
crypto api, but I was not sure if that is ready for use at that time.


Not being sure is different than being certain. As Andy noted, if that does
not work please poke Andy about the SHA-256 API he has which would enable
its use in kernel.

Right now this is just a crazy hack for *2* drivers. Its a lot of hacks for
just that, so no need to rush this in just yet.


I agree that there is no rush to get this in. I will rebase this on top
of the "[PATCH v7 00/14] firmware_loader changes for v4.18" series you recently
send as well as try to address all the remarks made sofar. I'm not entirely
sure when I will get around to this.

Regards,

Hans

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v5 2/5] efi: Add embedded peripheral firmware support

2018-05-13 Thread Hans de Goede

Hi,

On 05/04/2018 06:56 AM, Ard Biesheuvel wrote:

Hi Hans,

One comment below, which I missed in review before.

On 29 April 2018 at 11:35, Hans de Goede <hdego...@redhat.com> wrote:

Just like with PCI options ROMs, which we save in the setup_efi_pci*
functions from arch/x86/boot/compressed/eboot.c, the EFI code / ROM itself
sometimes may contain data which is useful/necessary for peripheral drivers
to have access to.

Specifically the EFI code may contain an embedded copy of firmware which
needs to be (re)loaded into the peripheral. Normally such firmware would be
part of linux-firmware, but in some cases this is not feasible, for 2
reasons:

1) The firmware is customized for a specific use-case of the chipset / use
with a specific hardware model, so we cannot have a single firmware file
for the chipset. E.g. touchscreen controller firmwares are compiled
specifically for the hardware model they are used with, as they are
calibrated for a specific model digitizer.

2) Despite repeated attempts we have failed to get permission to
redistribute the firmware. This is especially a problem with customized
firmwares, these get created by the chip vendor for a specific ODM and the
copyright may partially belong with the ODM, so the chip vendor cannot
give a blanket permission to distribute these.

This commit adds support for finding peripheral firmware embedded in the
EFI code and making this available to peripheral drivers through the
standard firmware loading mechanism.

Note we check the EFI_BOOT_SERVICES_CODE for embedded firmware near the end
of start_kernel(), just before calling rest_init(), this is on purpose
because the typical EFI_BOOT_SERVICES_CODE memory-segment is too large for
early_memremap(), so the check must be done after mm_init(). This relies
on EFI_BOOT_SERVICES_CODE not being free-ed until efi_free_boot_services()
is called, which means that this will only work on x86 for now.

Reported-by: Dave Olsthoorn <d...@bewaar.me>
Suggested-by: Peter Jones <pjo...@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheu...@linaro.org>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---

[...]

diff --git a/drivers/firmware/efi/embedded-firmware.c 
b/drivers/firmware/efi/embedded-firmware.c
new file mode 100644
index ..22a0f598b53d
--- /dev/null
+++ b/drivers/firmware/efi/embedded-firmware.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Support for extracting embedded firmware for peripherals from EFI code,
+ *
+ * Copyright (c) 2018 Hans de Goede <hdego...@redhat.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct embedded_fw {
+   struct list_head list;
+   const char *name;
+   void *data;
+   size_t length;
+};
+
+static LIST_HEAD(found_fw_list);
+
+static const struct dmi_system_id * const embedded_fw_table[] = {
+   NULL
+};
+
+/*
+ * Note the efi_check_for_embedded_firmwares() code currently makes the
+ * following 2 assumptions. This may needs to be revisited if embedded firmware
+ * is found where this is not true:
+ * 1) The firmware is only found in EFI_BOOT_SERVICES_CODE memory segments
+ * 2) The firmware always starts at an offset which is a multiple of 8 bytes
+ */
+static int __init efi_check_md_for_embedded_firmware(
+   efi_memory_desc_t *md, const struct efi_embedded_fw_desc *desc)
+{
+   struct embedded_fw *fw;
+   u64 i, size;
+   u32 crc;
+   u8 *mem;
+
+   size = md->num_pages << EFI_PAGE_SHIFT;
+   mem = memremap(md->phys_addr, size, MEMREMAP_WB);
+   if (!mem) {
+   pr_err("Error mapping EFI mem at %#llx\n", md->phys_addr);
+   return -ENOMEM;
+   }
+
+   size -= desc->length;
+   for (i = 0; i < size; i += 8) {
+   if (*((u64 *)(mem + i)) != *((u64 *)desc->prefix))
+   continue;
+


Please use the proper APIs here to cast u8* to u64*, i.e., either use
get_unaligned64() or use memcmp()


But we know the memory addresses are 64 bit aligned, so using
get_unaligned64 seems wrong, and I'm not sure if the compiler is
smart enough to optimize a memcmp to the single 64 bit integer comparison
we want done here.

Regards,

Hans




+   /* Seed with ~0, invert to match crc32 userspace utility */
+   crc = ~crc32(~0, mem + i, desc->length);
+   if (crc == desc->crc)
+   break;
+   }
+
+   memunmap(mem);
+
+   if (i >= size)
+   return -ENOENT;
+
+   pr_info("Found EFI embedded fw '%s' crc %08x\n", desc->name, desc->crc);
+
+   fw = kmalloc(sizeof(*fw), GFP_KERNEL);
+   if (!fw)
+   return -ENOMEM;
+
+   mem = memremap(md->phys_addr + i, desc->length, MEMREMAP_WB);
+   if (!mem) {
+   pr_err("Error mapping embedded firmware\n");
+   goto error_free_

Re: [PATCH v5 2/5] efi: Add embedded peripheral firmware support

2018-05-02 Thread Hans de Goede

Hi,

On 05/01/2018 09:29 PM, Andy Lutomirski wrote:

On Sun, Apr 29, 2018 at 2:36 AM Hans de Goede <hdego...@redhat.com> wrote:

+The EFI embedded-fw code works by scanning all EFI_BOOT_SERVICES_CODE

memory

+segments for an eight byte sequence matching prefix, if the prefix is

found it

+then does a crc32 over length bytes and if that matches makes a copy of

length

+bytes and adds that to its list with found firmwares.
+


Eww, gross.  Is there really no better way to do this?


I'm afraid not.


 Is the issue that
the EFI code does not intend to pass the firmware to the OS but that it has
a copy for its own purposes and that Linux is just going to hijack EFI's
copy?  If so, that's brilliant and terrible at the same time.


Yes that is exactly the issue / what it happening here.




+   for (i = 0; i < size; i += 8) {
+   if (*((u64 *)(mem + i)) != *((u64 *)desc->prefix))
+   continue;
+
+   /* Seed with ~0, invert to match crc32 userspace utility

*/

+   crc = ~crc32(~0, mem + i, desc->length);
+   if (crc == desc->crc)
+   break;
+   }


I hate to play the security card, but this stinks a bit.  The kernel
obviously needs to trust the EFI boot services code since the EFI boot
services code is free to modify the kernel image.  But your patch is not
actually getting this firmware blob from the boot services code via any
defined interface -- you're literally snarfing up the blob from a range of
memory.  I fully expect there to be any number of ways for untrustworthy
entities to inject malicious blobs into this memory range on quite a few
implementations.  For example, there are probably unauthenticated EFI
variables and even parts of USB sticks and such that get read into boot
services memory, and I see no reason at all to expect that nothing in the
so-called "boot services code" range is actually just plain old boot
services *heap*.

Fortunately, given your design, this is very easy to fix.  Just replace
CRC32 with SHA-256 or similar.  If you find the crypto api too ugly for
this purpose, I have patches that only need a small amount of dusting off
to give an entirely reasonable SHA-256 API in the kernel.


My main reason for going with crc32 is that the scanning happens before
the kernel is fully up and running (it happens just before the rest_init()
call in start_kernel() (from init/main.c) I'm open to using the
crypto api, but I was not sure if that is ready for use at that time.


(To be clear, I don't love my own suggestion here.  What I'd *really* like
to see is a better interface and no attempt to match the data to some
built-in hash at all.  In particular, there are plenty of devices for which
the driver wants access to a genuinely device-specific blob.  For example,
I'm typing this email while connected to a router that is running ath10k
and is using a calibration blob awkwardly snarfed out of flash somewhere.
It would be really nice if there was a way to pull a blob out of EFI space
that is marked, by EFI, as belonging to a particular device.  Then the
firmware could just pass it over without any particular verification.  But
since your code is literally scanning a wide swath of physical memory for
something that looks like a valid blob, I think you need to use a
cryptographically strong concept of validity.)


Yes ideally this would not be needed at all and/or use a well defined
interface, but alas we don't live in an ideal world :)

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v5 2/5] efi: Add embedded peripheral firmware support

2018-05-01 Thread Hans de Goede

Hi,

On 01-05-18 16:36, Mimi Zohar wrote:

[Cc'ing linux-security]

On Sun, 2018-04-29 at 11:35 +0200, Hans de Goede wrote:
[...]

diff --git a/drivers/base/firmware_loader/fallback_efi.c 
b/drivers/base/firmware_loader/fallback_efi.c
new file mode 100644
index ..82ba82f48a79
--- /dev/null
+++ b/drivers/base/firmware_loader/fallback_efi.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include 
+#include 
+#include 
+#include 
+
+#include "fallback.h"
+#include "firmware.h"
+
+int fw_get_efi_embedded_fw(struct device *dev, struct fw_priv *fw_priv,
+  enum fw_opt *opt_flags, int ret)
+{
+   enum kernel_read_file_id id = READING_FIRMWARE;


Please define a new kernel_read_file_id for this (eg.
READING_FIRMWARE_EFI_EMBEDDED).


Are you sure, I wonder how useful it is to add a new
kernel_read_file_id every time a new way to get firmware
comes up?

I especially wonder about the sense in adding a new id
given that the quite old FIRMWARE_PREALLOC_BUFFER is
still not supported / checked properly by the security code.

Anyways I can add a new id if you want me to, what about
when fw_get_efi_embedded_fw is reading into a driver allocated
buffer, do you want a separate EADING_FIRMWARE_EFI_EMBEDDED_PREALLOC_BUFFER
for that ?







+   size_t size, max = INT_MAX;
+   int rc;
+
+   if (!dev)
+   return ret;
+
+   if (!device_property_read_bool(dev, "efi-embedded-firmware"))
+   return ret;


Instead of calling security_kernel_post_read_file(), either in
device_property_read_bool() or here call security_kernel_read_file().

The pre read call is for deciding whether to allow this call
independent of the firmware being loaded, whereas the post security
call is currently being used by IMA-appraisal for verifying a
signature.  There might be other LSMs using the post hook as well.  As
there is no kernel signature associated with this firmware, use the
security pre read_file hook.


Only the pre hook?  I believe the post-hook should still be called too,
right? So that we've hashes of all loaded firmwares in the IMA core.

Regards,

Hans




thanks,

Mimi


+
+   *opt_flags |= FW_OPT_NO_WARN | FW_OPT_NOCACHE | FW_OPT_NOFALLBACK;
+
+   /* Already populated data member means we're loading into a buffer */
+   if (fw_priv->data) {
+   id = READING_FIRMWARE_PREALLOC_BUFFER;
+   max = fw_priv->allocated_size;
+   }
+
+   rc = efi_get_embedded_fw(fw_priv->fw_name, _priv->data, , max);
+   if (rc) {
+   dev_warn(dev, "Firmware %s not in EFI\n", fw_priv->fw_name);
+   return ret;
+   }
+
+   rc = security_kernel_post_read_file(NULL, fw_priv->data, size, id);
+   if (rc) {
+   if (id != READING_FIRMWARE_PREALLOC_BUFFER) {
+   vfree(fw_priv->data);
+   fw_priv->data = NULL;
+   }
+   return rc;
+   }
+
+   dev_dbg(dev, "using efi-embedded fw %s\n", fw_priv->fw_name);
+   fw_priv->size = size;
+   fw_state_done(fw_priv);
+   return 0;
+}



--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 0/4] Ignore unrealistically large option roms in EFI stub code

2018-05-01 Thread Hans de Goede

Hi,

On 29-04-18 13:06, Ard Biesheuvel wrote:

This is a continuation of Hans's work [0] to ignore bogus romimage/romsize
values in the EFI PCI I/O protocol instances exposed by some UEFI firmwares
on x86.

I have only build tested this, both on 32 and 64 bit x86.


I've tested this on both a device with a 32 bit UEFI and on a device with
a 64 bit UEFI, using a 64 bit kernel on both cases. The second device also
used to show the "failed to alloc mem for rom" errors and I can confirm
this series fixes this:

Tested-by: Hans de Goede <hdego...@redhat.com>

Regards,

Hans





Changes in v4:
- Deduplicate the 32 and 64 bit code paths so that the actual change needs
   to be applied only once. This requires some preparatory work (#1, #2, #3),
   of which the first one should go to -stable.

Changes in v3:
- Limit the rom-size to 16MiB to match the EFI spec

Changes in v2:
- Add the check to both __setup_efi_pci32 and __setup_efi_pci64 instead of
   only to __setup_efi_pci64, some CHT devices which need this still use a
   32 bit UEFI

[0] https://marc.info/?l=linux-efi=152494632116321

Ard Biesheuvel (3):
   efi: fix efi_pci_io_protocol32 prototype for mixed mode
   efi: align efi_pci_io_protocol typedefs to type naming convention
   efi/x86: fold __setup_efi_pci32 and __setup_efi_pci64 into one

Hans de Goede (1):
   efi/x86: Ignore unrealistically large option roms

  arch/x86/boot/compressed/eboot.c | 112 ++--
  include/linux/efi.h  |  14 +--
  2 files changed, 39 insertions(+), 87 deletions(-)


--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 1/5] efi: Export boot-services code and data as debugfs-blobs

2018-04-29 Thread Hans de Goede
Sometimes it is useful to be able to dump the efi boot-services code and
data. This commit adds these as debugfs-blobs to /sys/kernel/debug/efi,
but only if efi=debug is passed on the kernel-commandline as this requires
not freeing those memory-regions, which costs 20+ MB of RAM.

Reviewed-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
Acked-by: Ard Biesheuvel <ard.biesheu...@linaro.org>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
Changes in v5:
-Rename the EFI_BOOT_SERVICES flag to EFI_PRESERVE_BS_REGIONS

Changes in v4:
-Add new EFI_BOOT_SERVICES flag and use it to determine if the boot-services
 memory segments are available (and thus if it makes sense to register the
 debugfs bits for them)

Changes in v2:
-Do not call pr_err on debugfs call failures
---
 arch/x86/platform/efi/efi.c|  1 +
 arch/x86/platform/efi/quirks.c |  4 +++
 drivers/firmware/efi/efi.c | 53 ++
 include/linux/efi.h|  1 +
 4 files changed, 59 insertions(+)

diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 9061babfbc83..82f0836d 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -208,6 +208,7 @@ int __init efi_memblock_x86_reserve_range(void)
 efi.memmap.desc_version);
 
memblock_reserve(pmap, efi.memmap.nr_map * efi.memmap.desc_size);
+   set_bit(EFI_PRESERVE_BS_REGIONS, );
 
return 0;
 }
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 36c1f8b9f7e0..16bdb9e3b343 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -376,6 +376,10 @@ void __init efi_free_boot_services(void)
int num_entries = 0;
void *new, *new_md;
 
+   /* Keep all regions for /sys/kernel/debug/efi */
+   if (efi_enabled(EFI_DBG))
+   return;
+
for_each_efi_memory_desc(md) {
unsigned long long start = md->phys_addr;
unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 232f4915223b..1590e4d6a857 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -325,6 +326,55 @@ static __init int efivar_ssdt_load(void)
 static inline int efivar_ssdt_load(void) { return 0; }
 #endif
 
+#ifdef CONFIG_DEBUG_FS
+
+#define EFI_DEBUGFS_MAX_BLOBS 32
+
+static struct debugfs_blob_wrapper debugfs_blob[EFI_DEBUGFS_MAX_BLOBS];
+
+static void __init efi_debugfs_init(void)
+{
+   struct dentry *efi_debugfs;
+   efi_memory_desc_t *md;
+   char name[32];
+   int type_count[EFI_BOOT_SERVICES_DATA + 1] = {};
+   int i = 0;
+
+   efi_debugfs = debugfs_create_dir("efi", NULL);
+   if (IS_ERR_OR_NULL(efi_debugfs))
+   return;
+
+   for_each_efi_memory_desc(md) {
+   switch (md->type) {
+   case EFI_BOOT_SERVICES_CODE:
+   snprintf(name, sizeof(name), "boot_services_code%d",
+type_count[md->type]++);
+   break;
+   case EFI_BOOT_SERVICES_DATA:
+   snprintf(name, sizeof(name), "boot_services_data%d",
+type_count[md->type]++);
+   break;
+   default:
+   continue;
+   }
+
+   debugfs_blob[i].size = md->num_pages << EFI_PAGE_SHIFT;
+   debugfs_blob[i].data = memremap(md->phys_addr,
+   debugfs_blob[i].size,
+   MEMREMAP_WB);
+   if (!debugfs_blob[i].data)
+   continue;
+
+   debugfs_create_blob(name, 0400, efi_debugfs, _blob[i]);
+   i++;
+   if (i == EFI_DEBUGFS_MAX_BLOBS)
+   break;
+   }
+}
+#else
+static inline void efi_debugfs_init(void) {}
+#endif
+
 /*
  * We register the efi subsystem with the firmware subsystem and the
  * efivars subsystem with the efi subsystem, if the system was booted with
@@ -369,6 +419,9 @@ static int __init efisubsys_init(void)
goto err_remove_group;
}
 
+   if (efi_enabled(EFI_DBG) && efi_enabled(EFI_PRESERVE_BS_REGIONS))
+   efi_debugfs_init();
+
return 0;
 
 err_remove_group:
diff --git a/include/linux/efi.h b/include/linux/efi.h
index f1b7d68ac460..791088360c1e 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1144,6 +1144,7 @@ extern int __init efi_setup_pcdp_console(char *);
 #define EFI_DBG8   /* Print additional debug info 
at runtime */
 #define EFI_NX_PE_DATA 9   /* Can runtime data regions be mapped 
non-executable? */

[PATCH v5 2/5] efi: Add embedded peripheral firmware support

2018-04-29 Thread Hans de Goede
Just like with PCI options ROMs, which we save in the setup_efi_pci*
functions from arch/x86/boot/compressed/eboot.c, the EFI code / ROM itself
sometimes may contain data which is useful/necessary for peripheral drivers
to have access to.

Specifically the EFI code may contain an embedded copy of firmware which
needs to be (re)loaded into the peripheral. Normally such firmware would be
part of linux-firmware, but in some cases this is not feasible, for 2
reasons:

1) The firmware is customized for a specific use-case of the chipset / use
with a specific hardware model, so we cannot have a single firmware file
for the chipset. E.g. touchscreen controller firmwares are compiled
specifically for the hardware model they are used with, as they are
calibrated for a specific model digitizer.

2) Despite repeated attempts we have failed to get permission to
redistribute the firmware. This is especially a problem with customized
firmwares, these get created by the chip vendor for a specific ODM and the
copyright may partially belong with the ODM, so the chip vendor cannot
give a blanket permission to distribute these.

This commit adds support for finding peripheral firmware embedded in the
EFI code and making this available to peripheral drivers through the
standard firmware loading mechanism.

Note we check the EFI_BOOT_SERVICES_CODE for embedded firmware near the end
of start_kernel(), just before calling rest_init(), this is on purpose
because the typical EFI_BOOT_SERVICES_CODE memory-segment is too large for
early_memremap(), so the check must be done after mm_init(). This relies
on EFI_BOOT_SERVICES_CODE not being free-ed until efi_free_boot_services()
is called, which means that this will only work on x86 for now.

Reported-by: Dave Olsthoorn <d...@bewaar.me>
Suggested-by: Peter Jones <pjo...@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheu...@linaro.org>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
Changes in v5:
-Rename the EFI_BOOT_SERVICES flag to EFI_PRESERVE_BS_REGIONS

Changes in v4:
-Drop note in docs about EFI_FIRMWARE_VOLUME_PROTOCOL, it is not part of
 UEFI proper, so the EFI maintainers don't want us referring people to it
-Use new EFI_BOOT_SERVICES flag
-Put the new fw_get_efi_embedded_fw() function in its own fallback_efi.c
 file which only gets built when EFI_EMBEDDED_FIRMWARE is selected
-Define an empty stub for fw_get_efi_embedded_fw() in fallback.h hwen
 EFI_EMBEDDED_FIRMWARE is not selected, to avoid the need for #ifdefs
 in firmware_loader/main.c
-Properly call security_kernel_post_read_file() on the firmware returned
 by efi_get_embedded_fw() to make sure that we are allowed to use it

Changes in v3:
-Fix the docs using "efi-embedded-fw" as property name instead of
 "efi-embedded-firmware"

Changes in v2:
-Rebased on driver-core/driver-core-next
-Add documentation describing the EFI embedded firmware mechanism to:
 Documentation/driver-api/firmware/request_firmware.rst
-Add a new EFI_EMBEDDED_FIRMWARE Kconfig bool and only build the embedded
 fw support if this is set. This is an invisible option which should be
 selected by drivers which need this
-Remove the efi_embedded_fw_desc and dmi_system_id-s for known devices
 from the efi-embedded-fw code, instead drivers using this are expected to
 export a dmi_system_id array, with each entries' driver_data pointing to a
 efi_embedded_fw_desc struct and register this with the efi-embedded-fw code
-Use kmemdup to make a copy instead of efi_mem_reserve()-ing the firmware,
 this avoids us messing with the EFI memmap and avoids the need to make
 changes to efi_mem_desc_lookup()
-Make the firmware-loader code only fallback to efi_get_embedded_fw() if the
 passed in device has the "efi-embedded-firmware" device-property bool set
-Skip usermodehelper fallback when "efi-embedded-firmware" device-property
 is set
---
 .../driver-api/firmware/request_firmware.rst  |  66 
 drivers/base/firmware_loader/Makefile |   1 +
 drivers/base/firmware_loader/fallback.h   |  12 ++
 drivers/base/firmware_loader/fallback_efi.c   |  51 ++
 drivers/base/firmware_loader/main.c   |   2 +
 drivers/firmware/efi/Kconfig  |   3 +
 drivers/firmware/efi/Makefile |   1 +
 drivers/firmware/efi/embedded-firmware.c  | 149 ++
 include/linux/efi.h   |   6 +
 include/linux/efi_embedded_fw.h   |  25 +++
 init/main.c   |   3 +
 11 files changed, 319 insertions(+)
 create mode 100644 drivers/base/firmware_loader/fallback_efi.c
 create mode 100644 drivers/firmware/efi/embedded-firmware.c
 create mode 100644 include/linux/efi_embedded_fw.h

diff --git a/Documentation/driver-api/firmware/request_firmware.rst 
b/Documentation/driver-api/firmware/request_firmware.rst
index c8bddbdcfd10..560dfed76e38 100644
--- a/Documentation/driver-api/firmware/request_firmware.

[PATCH v5 5/5] platform/x86: touchscreen_dmi: Add info for the Chuwi Vi8 Plus tablet

2018-04-29 Thread Hans de Goede
Add touchscreen info for the Chuwi Vi8 Plus tablet. This tablet uses a
Chipone ICN8505 touchscreen controller, with the firmware used by the
touchscreen embedded in the EFI firmware.

Acked-by: Andy Shevchenko <andy.shevche...@gmail.com>
Acked-by: Ard Biesheuvel <ard.biesheu...@linaro.org>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 drivers/platform/x86/touchscreen_dmi.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/drivers/platform/x86/touchscreen_dmi.c 
b/drivers/platform/x86/touchscreen_dmi.c
index 6488cd50ba79..5fdb6fe878f4 100644
--- a/drivers/platform/x86/touchscreen_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -301,6 +301,22 @@ static const struct ts_dmi_data teclast_x3_plus_data = {
.properties = teclast_x3_plus_props,
 };
 
+static const struct property_entry efi_embedded_fw_props[] = {
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
+   { }
+};
+
+static const struct ts_dmi_data chuwi_vi8_plus_data = {
+   .embedded_fw = {
+   .name   = "chipone/icn8505-HAMP0002.fw",
+   .prefix = { 0xb0, 0x07, 0x00, 0x00, 0xe4, 0x07, 0x00, 0x00 },
+   .length = 35012,
+   .crc= 0x74dfd3fc,
+   },
+   .acpi_name  = "CHPN0001:00",
+   .properties = efi_embedded_fw_props,
+};
+
 const struct dmi_system_id touchscreen_dmi_table[] = {
{
/* CUBE iwork8 Air */
@@ -487,6 +503,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"),
},
},
+   {
+   /* Chuwi Vi8 Plus (CWI506) */
+   .driver_data = (void *)_vi8_plus_data,
+   .matches = {
+   DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
+   DMI_MATCH(DMI_PRODUCT_NAME, "D2D3_Vi8A1"),
+   DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+   },
+   },
{ },
 };
 
-- 
2.17.0

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 4/5] platform/x86: touchscreen_dmi: Add EFI embedded firmware info support

2018-04-29 Thread Hans de Goede
Sofar we have been unable to get permission from the vendors to put the
firmware for touchscreens listed in touchscreen_dmi in linux-firmware.

Some of the tablets with such a touchscreen have a touchscreen driver, and
thus a copy of the firmware, as part of their EFI code.

This commit adds the necessary info for the new EFI embedded-firmware code
to extract these firmwares, making the touchscreen work OOTB without the
user needing to manually add the firmware.

Acked-by: Andy Shevchenko <andy.shevche...@gmail.com>
Acked-by: Ard Biesheuvel <ard.biesheu...@linaro.org>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 drivers/firmware/efi/embedded-firmware.c |  3 +++
 drivers/platform/x86/Kconfig |  1 +
 drivers/platform/x86/touchscreen_dmi.c   | 26 +++-
 include/linux/efi_embedded_fw.h  |  2 ++
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/embedded-firmware.c 
b/drivers/firmware/efi/embedded-firmware.c
index 22a0f598b53d..36a93a6938f0 100644
--- a/drivers/firmware/efi/embedded-firmware.c
+++ b/drivers/firmware/efi/embedded-firmware.c
@@ -23,6 +23,9 @@ struct embedded_fw {
 static LIST_HEAD(found_fw_list);
 
 static const struct dmi_system_id * const embedded_fw_table[] = {
+#ifdef CONFIG_TOUCHSCREEN_DMI
+   touchscreen_dmi_table,
+#endif
NULL
 };
 
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 7ff206e5edfe..cc4d95459190 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1199,6 +1199,7 @@ config INTEL_TURBO_MAX_3
 config TOUCHSCREEN_DMI
bool "DMI based touchscreen configuration info"
depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD
+   select EFI_EMBEDDED_FIRMWARE if EFI
---help---
  Certain ACPI based tablets with e.g. Silead or Chipone touchscreens
  do not have enough data in ACPI tables for the touchscreen driver to
diff --git a/drivers/platform/x86/touchscreen_dmi.c 
b/drivers/platform/x86/touchscreen_dmi.c
index 87fc839b28f7..6488cd50ba79 100644
--- a/drivers/platform/x86/touchscreen_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -15,12 +15,15 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 
 struct ts_dmi_data {
+   /* The EFI embedded-fw code expects this to be the first member! */
+   struct efi_embedded_fw_desc embedded_fw;
const char *acpi_name;
const struct property_entry *properties;
 };
@@ -31,10 +34,17 @@ static const struct property_entry cube_iwork8_air_props[] 
= {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
{ }
 };
 
 static const struct ts_dmi_data cube_iwork8_air_data = {
+   .embedded_fw = {
+   .name   = "silead/gsl3670-cube-iwork8-air.fw",
+   .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+   .length = 38808,
+   .crc= 0xfecde51f,
+   },
.acpi_name  = "MSSL1680:00",
.properties = cube_iwork8_air_props,
 };
@@ -119,10 +129,17 @@ static const struct property_entry pipo_w2s_props[] = {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name",
  "gsl1680-pipo-w2s.fw"),
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
{ }
 };
 
 static const struct ts_dmi_data pipo_w2s_data = {
+   .embedded_fw = {
+   .name   = "silead/gsl1680-pipo-w2s.fw",
+   .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+   .length = 39072,
+   .crc= 0x28d5dc6c,
+   },
.acpi_name  = "MSSL1680:00",
.properties = pipo_w2s_props,
 };
@@ -162,10 +179,17 @@ static const struct property_entry chuwi_hi8_pro_props[] 
= {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"),
PROPERTY_ENTRY_BOOL("silead,home-button"),
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
{ }
 };
 
 static const struct ts_dmi_data chuwi_hi8_pro_data = {
+   .embedded_fw = {
+   .name   = "silead/gsl3680-chuwi-hi8-pro.fw",
+   .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+   .length = 39864,
+   .crc= 0xfe2bedba,
+   },
.acpi_name  = "MSSL1680:00",
.properties = chuwi_hi8_pro_props,
 };
@@ -277,7 +301,7 @@ static const struct ts_

[PATCH v5 0/5] efi/firmware/platform-x86: Add EFI embedded fw support

2018-04-29 Thread Hans de Goede
Hi All,

Here is v5 of my patch-set to add support for EFI embedded fw to the kernel.

Changes since v4:
-Rename the EFI_BOOT_SERVICES flag to EFI_PRESERVE_BS_REGIONS

So I think this patch-set is getting close to ready for merging, which
brings us to the question of how to merge this, I think that patches 1
and 2 should probably both be merged through the same tree. Then an
unmutable branch should be created on that tree, merged into the
platform/x86 tree and then the last 3 patches can be merged through
that tree.

Ard has already indicated he is fine with the EFI bits going upstream
through another tree, so perhaps patches 1-2 can be merged through the
firmware-loader-tree and then do an unmutable branch on the
firmware-loader-tree for the platform/x86 tree to merge?

I don't think taking all 5 through 1 tree is a good idea because of
the file rename under platform/x86.


For the record here are the cover letters of the previous versions:

Changes since v3:
-Drop note in docs about EFI_FIRMWARE_VOLUME_PROTOCOL, it is not part of
 UEFI proper, so the EFI maintainers don't want us referring people to it
-Use new EFI_BOOT_SERVICES flag
-Put the new fw_get_efi_embedded_fw() function in its own fallback_efi.c
 file which only gets built when EFI_EMBEDDED_FIRMWARE is selected
-Define an empty stub for fw_get_efi_embedded_fw() in fallback.h hwen
 EFI_EMBEDDED_FIRMWARE is not selected, to avoid the need for #ifdefs
 in firmware_loader/main.c
-Properly call security_kernel_post_read_file() on the firmware returned
 by efi_get_embedded_fw() to make sure that we are allowed to use it

The 3 most prominent changes in v2 are:

1) Add documentation describing the EFI embedded firmware mechanism to:
   Documentation/driver-api/firmware/request_firmware.rst

2) Instead of having a single dmi_system_id array with its driver_data
   members pointing to efi_embedded_fw_desc structs, have the drivers which
   need EFI embedded-fw support export a dmi_system_id array and register
   that with the EFI embedded-fw code

   This series also includes the first driver to use this, in the form of
   the touchscreen_dmi code (formerly silead_dmi) from drivers/platfrom/x86

3) As discussed during the review of v1 we want to make the firmware_loader
   code fallback to EFI embedded-fw optional.  Rather the adding yet another
   firmware_request_foo variant for this, with the risk of later also needing
   firmware_request_foo_nowait, etc. variants I've decided to make the code
   check if the device has a "efi-embedded-firmware" device-property bool set.

   This also seemed better because the same driver may want to use the
   fallback on some systems, but not on others since e.g. not all (x86)
   systems with a silead touchscreen have their touchscreen firmware embedded
   in their EFI.

   Note that (as discussed) when the EFI fallback path is requested, the
   usermodehelper fallback path is skipped.

Here is the full changelog of patch 2/5 which is where most of the changes are:

Changes in v2:
-Rebased on driver-core/driver-core-next
-Add documentation describing the EFI embedded firmware mechanism to:
 Documentation/driver-api/firmware/request_firmware.rst
-Add a new EFI_EMBEDDED_FIRMWARE Kconfig bool and only build the embedded
 fw support if this is set. This is an invisible option which should be
 selected by drivers which need this
-Remove the efi_embedded_fw_desc and dmi_system_id-s for known devices
 from the efi-embedded-fw code, instead drivers using this are expected to
 export a dmi_system_id array, with each entries' driver_data pointing to a
 efi_embedded_fw_desc struct and register this with the efi-embedded-fw code
-Use kmemdup to make a copy instead of efi_mem_reserve()-ing the firmware,
 this avoids us messing with the EFI memmap and avoids the need to make
 changes to efi_mem_desc_lookup()
-Make the firmware-loader code only fallback to efi_get_embedded_fw() if the
 passed in device has the "efi-embedded-firmware" device-property bool set
-Skip usermodehelper fallback when "efi-embedded-firmware" device-property
 is set

Patches 3-5 are new and implement using the EFI embedded-fw mechanism for
Silead gsl and Chipone icn8505 touchscreens on x86 devices.

Regards,

Hans

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3] efi: Ignore unrealistically large option roms

2018-04-29 Thread Hans de Goede

Hi,

On 29-04-18 11:07, Ard Biesheuvel wrote:

On 29 April 2018 at 10:40, Hans de Goede <hdego...@redhat.com> wrote:

Hi,


On 29-04-18 09:43, Ingo Molnar wrote:



* Hans de Goede <hdego...@redhat.com> wrote:


diff --git a/arch/x86/boot/compressed/eboot.c
b/arch/x86/boot/compressed/eboot.c
index 47d3efff6805..8650ab268ee7 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -122,7 +122,14 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci,
struct pci_setup_rom **__rom)
 if (status != EFI_SUCCESS)
 return status;
   - if (!pci->romimage || !pci->romsize)
+   /*
+* Some firmwares contain EFI function pointers at the place
where the
+* romimage and romsize fields are supposed to be. Typically the
EFI
+* code is mapped at high addresses, translating to an
unrealistically
+* large romsize. The UEFI spec limits the size of option ROMs to
16
+* MiB so we reject any roms over 16 MiB in size to catch this.
+*/
+   if (!pci->romimage || !pci->romsize || pci->romsize > 0x100)
 return EFI_INVALID_PARAMETER;
 size = pci->romsize + sizeof(*rom);
@@ -230,7 +237,14 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci,
struct pci_setup_rom **__rom)
 if (status != EFI_SUCCESS)
 return status;
   - if (!pci->romimage || !pci->romsize)
+   /*
+* Some firmwares contain EFI function pointers at the place
where the
+* romimage and romsize fields are supposed to be. Typically the
EFI
+* code is mapped at high addresses, translating to an
unrealistically
+* large romsize. The UEFI spec limits the size of option ROMs to
16
+* MiB so we reject any roms over 16 MiB in size to catch this.
+*/
+   if (!pci->romimage || !pci->romsize || pci->romsize > 0x100)
 return EFI_INVALID_PARAMETER;



Any reason why this couldn't be factored out into a efi_check_rom(pci)
kind of
helper function



The pci pointer is of 2 different types:

__setup_efi_pci32(efi_pci_io_protocol_32 *pci, ...
__setup_efi_pci64(efi_pci_io_protocol_64 *pci, ...

I guess I could give the helper a romimage and romsize argument to get
around that.
Ard, do you want me to do a v4 with such a helper ?



I think Lukas has a point, although I shouldn't expect you to implement that.

I will look into this myself, and rebase your patch on top of that.


Ok, thanks.

Regards,

Hans

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3] efi: Ignore unrealistically large option roms

2018-04-29 Thread Hans de Goede

Hi,

On 29-04-18 09:43, Ingo Molnar wrote:


* Hans de Goede <hdego...@redhat.com> wrote:


diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 47d3efff6805..8650ab268ee7 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -122,7 +122,14 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct 
pci_setup_rom **__rom)
if (status != EFI_SUCCESS)
return status;
  
-	if (!pci->romimage || !pci->romsize)

+   /*
+* Some firmwares contain EFI function pointers at the place where the
+* romimage and romsize fields are supposed to be. Typically the EFI
+* code is mapped at high addresses, translating to an unrealistically
+* large romsize. The UEFI spec limits the size of option ROMs to 16
+* MiB so we reject any roms over 16 MiB in size to catch this.
+*/
+   if (!pci->romimage || !pci->romsize || pci->romsize > 0x100)
return EFI_INVALID_PARAMETER;
  
  	size = pci->romsize + sizeof(*rom);

@@ -230,7 +237,14 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct 
pci_setup_rom **__rom)
if (status != EFI_SUCCESS)
return status;
  
-	if (!pci->romimage || !pci->romsize)

+   /*
+* Some firmwares contain EFI function pointers at the place where the
+* romimage and romsize fields are supposed to be. Typically the EFI
+* code is mapped at high addresses, translating to an unrealistically
+* large romsize. The UEFI spec limits the size of option ROMs to 16
+* MiB so we reject any roms over 16 MiB in size to catch this.
+*/
+   if (!pci->romimage || !pci->romsize || pci->romsize > 0x100)
return EFI_INVALID_PARAMETER;


Any reason why this couldn't be factored out into a efi_check_rom(pci) kind of
helper function


The pci pointer is of 2 different types:

__setup_efi_pci32(efi_pci_io_protocol_32 *pci, ...
__setup_efi_pci64(efi_pci_io_protocol_64 *pci, ...

I guess I could give the helper a romimage and romsize argument to get around 
that.
Ard, do you want me to do a v4 with such a helper ?

Regards,

Hans


--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3] efi: Ignore unrealistically large option roms

2018-04-28 Thread Hans de Goede
setup_efi_pci() tries to save a copy of each PCI option ROM as this may
be necessary for the device driver for the PCI device to have access too.

On some systems the efi_pci_io_protocol's romimage and romsize fields
contain invalid data, which looks a bit like pointers pointing back into
other EFI code or data. Interpreting these pointers as romsize leads to
a very large value and if we then try to alloc this amount of memory to
save a copy the alloc call fails.

This leads to a "Failed to alloc mem for rom" error being printed on the
EFI console for each PCI device.

This commit avoids the printing of these errors, by checking romsize before
doing the alloc and if it is larger then the EFI spec limit of 16 MiB
silently ignore the ROM fields instead of trying to alloc mem and fail.

Reviewed-by: Ard Biesheuvel <ard.biesheu...@linaro.org>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
Changes in v3:
-Limit the rom-size to 16MiB to match the EFI spec

Changes in v2:
-Add the check to both __setup_efi_pci32 and __setup_efi_pci64 instead of
 only to __setup_efi_pci64, some CHT devices which need this still use a
 32 bit UEFI
---
 arch/x86/boot/compressed/eboot.c | 18 --
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 47d3efff6805..8650ab268ee7 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -122,7 +122,14 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct 
pci_setup_rom **__rom)
if (status != EFI_SUCCESS)
return status;
 
-   if (!pci->romimage || !pci->romsize)
+   /*
+* Some firmwares contain EFI function pointers at the place where the
+* romimage and romsize fields are supposed to be. Typically the EFI
+* code is mapped at high addresses, translating to an unrealistically
+* large romsize. The UEFI spec limits the size of option ROMs to 16
+* MiB so we reject any roms over 16 MiB in size to catch this.
+*/
+   if (!pci->romimage || !pci->romsize || pci->romsize > 0x100)
return EFI_INVALID_PARAMETER;
 
size = pci->romsize + sizeof(*rom);
@@ -230,7 +237,14 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct 
pci_setup_rom **__rom)
if (status != EFI_SUCCESS)
return status;
 
-   if (!pci->romimage || !pci->romsize)
+   /*
+* Some firmwares contain EFI function pointers at the place where the
+* romimage and romsize fields are supposed to be. Typically the EFI
+* code is mapped at high addresses, translating to an unrealistically
+* large romsize. The UEFI spec limits the size of option ROMs to 16
+* MiB so we reject any roms over 16 MiB in size to catch this.
+*/
+   if (!pci->romimage || !pci->romsize || pci->romsize > 0x100)
return EFI_INVALID_PARAMETER;
 
size = pci->romsize + sizeof(*rom);
-- 
2.17.0

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] efi: Ignore unrealistically large option roms

2018-04-28 Thread Hans de Goede

Hi,

On 28-04-18 08:40, Ard Biesheuvel wrote:

Hi Hans,

On 27 April 2018 at 23:35, Hans de Goede <hdego...@redhat.com> wrote:

setup_efi_pci() tries to save a copy of each PCI option ROM as this may
be necessary for the device driver for the PCI device to have access too.

On some systems the efi_pci_io_protocol_64's romimage and romsize fields
contain invalid data, which looks a bit like pointers pointing back into
other EFI code or data. Interpreting these pointers as romsize leads to
a very large value and if we then try to alloc this amount of memory to
save a copy the alloc call fails.

This leads to a "Failed to alloc mem for rom" error being printed on the
EFI console for each PCI device.

This commit avoids the printing of these errors, by checking romsize
before doing the alloc and if it is larger then 256M silently ignore the
ROM fields instead of trying to alloc mem and fail.



The UEFI spec limits the size of option ROMs to 16 MiB, so I'd prefer
we use that as the upper bound instead.

With that changed,

Reviewed-by: Ard Biesheuvel <ard.biesheu...@linaro.org>


Thanks for the review, fixed for v3 which I'm about to send.


or I can take it via the EFI tree if desired.


I've no preference for how this goes upstream. x86 folks, please let
us know if you will take this, or if you would prefer for this to
go upstream through the EFI tree.

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] efi: Ignore unrealistically large option roms

2018-04-27 Thread Hans de Goede
setup_efi_pci() tries to save a copy of each PCI option ROM as this may
be necessary for the device driver for the PCI device to have access too.

On some systems the efi_pci_io_protocol_64's romimage and romsize fields
contain invalid data, which looks a bit like pointers pointing back into
other EFI code or data. Interpreting these pointers as romsize leads to
a very large value and if we then try to alloc this amount of memory to
save a copy the alloc call fails.

This leads to a "Failed to alloc mem for rom" error being printed on the
EFI console for each PCI device.

This commit avoids the printing of these errors, by checking romsize
before doing the alloc and if it is larger then 256M silently ignore the
ROM fields instead of trying to alloc mem and fail.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
Changes in v2:
-Add the check to both __setup_efi_pci32 and __setup_efi_pci64 instead of
 only to __setup_efi_pci64, some CHT devices which need this still use a
 32 bit UEFI
---
 arch/x86/boot/compressed/eboot.c | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 47d3efff6805..6d3257a459c8 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -122,7 +122,13 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct 
pci_setup_rom **__rom)
if (status != EFI_SUCCESS)
return status;
 
-   if (!pci->romimage || !pci->romsize)
+   /*
+* Some firmwares contain EFI function pointers at the place where the
+* romimage and romsize fields are supposed to be. Typically the EFI
+* code is mapped at high addresses, translating to an unrealistically
+* large romsize. We reject any roms over 256M in size to catch this.
+*/
+   if (!pci->romimage || !pci->romsize || pci->romsize > 0x1000)
return EFI_INVALID_PARAMETER;
 
size = pci->romsize + sizeof(*rom);
@@ -230,7 +236,13 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct 
pci_setup_rom **__rom)
if (status != EFI_SUCCESS)
return status;
 
-   if (!pci->romimage || !pci->romsize)
+   /*
+* Some firmwares contain EFI function pointers at the place where the
+* romimage and romsize fields are supposed to be. Typically the EFI
+* code is mapped at high addresses, translating to an unrealistically
+* large romsize. We reject any roms over 256M in size to catch this.
+*/
+   if (!pci->romimage || !pci->romsize || pci->romsize > 0x1000)
return EFI_INVALID_PARAMETER;
 
size = pci->romsize + sizeof(*rom);
-- 
2.16.2

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 1/5] efi: Export boot-services code and data as debugfs-blobs

2018-04-27 Thread Hans de Goede

Hi,

On 26-04-18 23:35, Ard Biesheuvel wrote:

On 26 April 2018 at 23:02, Hans de Goede <hdego...@redhat.com> wrote:

Hi,


On 26-04-18 18:51, Ard Biesheuvel wrote:


On 26 April 2018 at 14:06, Hans de Goede <hdego...@redhat.com> wrote:


Sometimes it is useful to be able to dump the efi boot-services code and
data. This commit adds these as debugfs-blobs to /sys/kernel/debug/efi,
but only if efi=debug is passed on the kernel-commandline as this
requires
not freeing those memory-regions, which costs 20+ MB of RAM.

Reviewed-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
Changes in v4:
-Add new EFI_BOOT_SERVICES flag and use it to determine if the
boot-services
   memory segments are available (and thus if it makes sense to register
the
   debugfs bits for them)

Changes in v2:
-Do not call pr_err on debugfs call failures
---
   arch/x86/platform/efi/efi.c|  1 +
   arch/x86/platform/efi/quirks.c |  4 +++
   drivers/firmware/efi/efi.c | 53 ++
   include/linux/efi.h|  1 +
   4 files changed, 59 insertions(+)

diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 9061babfbc83..568b7ee3d323 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -208,6 +208,7 @@ int __init efi_memblock_x86_reserve_range(void)
   efi.memmap.desc_version);

  memblock_reserve(pmap, efi.memmap.nr_map *
efi.memmap.desc_size);
+   set_bit(EFI_BOOT_SERVICES, );



I think it would be better if the flag conveys whether boot services
regions are being preserved, because they will always exist when
EFI_BOOT is set.
The name should then reflect that as well, e.g., EFI_PRESERVE_BS_REGIONS.



Ok, I will rename the flag to EFI_PRESERVE_BS_REGIONS for v5
(I'm going to wait a bit with sending out v5 to give others a change
  to comment on v4).


  return 0;
   }
diff --git a/arch/x86/platform/efi/quirks.c
b/arch/x86/platform/efi/quirks.c
index 36c1f8b9f7e0..16bdb9e3b343 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -376,6 +376,10 @@ void __init efi_free_boot_services(void)
  int num_entries = 0;
  void *new, *new_md;

+   /* Keep all regions for /sys/kernel/debug/efi */
+   if (efi_enabled(EFI_DBG))
+   return;
+



Why is this only necessary when EFI_DBG is enabled? How are you
ensuring that the firmware is still in memory when the subsequent
patches start relying on that?



The 2nd patch in this series makes init/main.c call
efi_check_for_embedded_firmwares() before efi_free_boot_services(),
efi_check_for_embedded_firmwares() then walks the dmi_system_id-s
"registered" (its a static list) by drivers and if their is a dmi_match
searches for the firmware described by the dmi_system_id.driver_data
ptr. If a firmware gets found it gets memdup-ed, so that we do not
have to keep all of the boot-services code around.



Right, thanks for clearing that up.

So that means that preserving the boot regions is really only
necessary if you want to inspect them via debugfs, and the firmware
loader does not rely on that. I missed that part.

That means the only reason we have the new flag is to ensure that the
shared debugfs code only exposes the boot services regions if they
were preserved to begin with by the arch code, right?


Mostly right, since we have the flag now anyways I'm also using
it as a condition to call efi_check_for_embedded_firmwares(),
efi_check_for_embedded_firmwares() needs to happen after mm_init() (*)
and on non x86 the boot-services code/data is long gone then so
there is nothing for efi_check_for_embedded_firmwares() to look at.


If so, after the flag rename:

Acked-by: Ard Biesheuvel <ard.biesheu...@linaro.org>


I assume that the "mostly right" is good enough and I'm going to
add your Acked-by for the next version. Let me know if you've
any objections against that.

Regards,

Hans


*) efi_check_for_embedded_firmwares() mremap()s the boot-services
memory segments to scan then and they are too big for early_mremap()

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 1/5] efi: Export boot-services code and data as debugfs-blobs

2018-04-26 Thread Hans de Goede

Hi,

On 26-04-18 18:51, Ard Biesheuvel wrote:

On 26 April 2018 at 14:06, Hans de Goede <hdego...@redhat.com> wrote:

Sometimes it is useful to be able to dump the efi boot-services code and
data. This commit adds these as debugfs-blobs to /sys/kernel/debug/efi,
but only if efi=debug is passed on the kernel-commandline as this requires
not freeing those memory-regions, which costs 20+ MB of RAM.

Reviewed-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
Changes in v4:
-Add new EFI_BOOT_SERVICES flag and use it to determine if the boot-services
  memory segments are available (and thus if it makes sense to register the
  debugfs bits for them)

Changes in v2:
-Do not call pr_err on debugfs call failures
---
  arch/x86/platform/efi/efi.c|  1 +
  arch/x86/platform/efi/quirks.c |  4 +++
  drivers/firmware/efi/efi.c | 53 ++
  include/linux/efi.h|  1 +
  4 files changed, 59 insertions(+)

diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 9061babfbc83..568b7ee3d323 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -208,6 +208,7 @@ int __init efi_memblock_x86_reserve_range(void)
  efi.memmap.desc_version);

 memblock_reserve(pmap, efi.memmap.nr_map * efi.memmap.desc_size);
+   set_bit(EFI_BOOT_SERVICES, );



I think it would be better if the flag conveys whether boot services
regions are being preserved, because they will always exist when
EFI_BOOT is set.
The name should then reflect that as well, e.g., EFI_PRESERVE_BS_REGIONS.


Ok, I will rename the flag to EFI_PRESERVE_BS_REGIONS for v5
(I'm going to wait a bit with sending out v5 to give others a change
 to comment on v4).


 return 0;
  }
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 36c1f8b9f7e0..16bdb9e3b343 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -376,6 +376,10 @@ void __init efi_free_boot_services(void)
 int num_entries = 0;
 void *new, *new_md;

+   /* Keep all regions for /sys/kernel/debug/efi */
+   if (efi_enabled(EFI_DBG))
+   return;
+


Why is this only necessary when EFI_DBG is enabled? How are you
ensuring that the firmware is still in memory when the subsequent
patches start relying on that?


The 2nd patch in this series makes init/main.c call
efi_check_for_embedded_firmwares() before efi_free_boot_services(),
efi_check_for_embedded_firmwares() then walks the dmi_system_id-s
"registered" (its a static list) by drivers and if their is a dmi_match
searches for the firmware described by the dmi_system_id.driver_data
ptr. If a firmware gets found it gets memdup-ed, so that we do not
have to keep all of the boot-services code around.

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 2/5] efi: Add embedded peripheral firmware support

2018-04-26 Thread Hans de Goede
Just like with PCI options ROMs, which we save in the setup_efi_pci*
functions from arch/x86/boot/compressed/eboot.c, the EFI code / ROM itself
sometimes may contain data which is useful/necessary for peripheral drivers
to have access to.

Specifically the EFI code may contain an embedded copy of firmware which
needs to be (re)loaded into the peripheral. Normally such firmware would be
part of linux-firmware, but in some cases this is not feasible, for 2
reasons:

1) The firmware is customized for a specific use-case of the chipset / use
with a specific hardware model, so we cannot have a single firmware file
for the chipset. E.g. touchscreen controller firmwares are compiled
specifically for the hardware model they are used with, as they are
calibrated for a specific model digitizer.

2) Despite repeated attempts we have failed to get permission to
redistribute the firmware. This is especially a problem with customized
firmwares, these get created by the chip vendor for a specific ODM and the
copyright may partially belong with the ODM, so the chip vendor cannot
give a blanket permission to distribute these.

This commit adds support for finding peripheral firmware embedded in the
EFI code and making this available to peripheral drivers through the
standard firmware loading mechanism.

Note we check the EFI_BOOT_SERVICES_CODE for embedded firmware near the end
of start_kernel(), just before calling rest_init(), this is on purpose
because the typical EFI_BOOT_SERVICES_CODE memory-segment is too large for
early_memremap(), so the check must be done after mm_init(). This relies
on EFI_BOOT_SERVICES_CODE not being free-ed until efi_free_boot_services()
is called, which means that this will only work on x86 for now.

Reported-by: Dave Olsthoorn <d...@bewaar.me>
Suggested-by: Peter Jones <pjo...@redhat.com>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
Changes in v4:
-Drop note in docs about EFI_FIRMWARE_VOLUME_PROTOCOL, it is not part of
 UEFI proper, so the EFI maintainers don't want us referring people to it
-Use new EFI_BOOT_SERVICES flag
-Put the new fw_get_efi_embedded_fw() function in its own fallback_efi.c
 file which only gets built when EFI_EMBEDDED_FIRMWARE is selected
-Define an empty stub for fw_get_efi_embedded_fw() in fallback.h hwen
 EFI_EMBEDDED_FIRMWARE is not selected, to avoid the need for #ifdefs
 in firmware_loader/main.c
-Properly call security_kernel_post_read_file() on the firmware returned
 by efi_get_embedded_fw() to make sure that we are allowed to use it

Changes in v3:
-Fix the docs using "efi-embedded-fw" as property name instead of
 "efi-embedded-firmware"

Changes in v2:
-Rebased on driver-core/driver-core-next
-Add documentation describing the EFI embedded firmware mechanism to:
 Documentation/driver-api/firmware/request_firmware.rst
-Add a new EFI_EMBEDDED_FIRMWARE Kconfig bool and only build the embedded
 fw support if this is set. This is an invisible option which should be
 selected by drivers which need this
-Remove the efi_embedded_fw_desc and dmi_system_id-s for known devices
 from the efi-embedded-fw code, instead drivers using this are expected to
 export a dmi_system_id array, with each entries' driver_data pointing to a
 efi_embedded_fw_desc struct and register this with the efi-embedded-fw code
-Use kmemdup to make a copy instead of efi_mem_reserve()-ing the firmware,
 this avoids us messing with the EFI memmap and avoids the need to make
 changes to efi_mem_desc_lookup()
-Make the firmware-loader code only fallback to efi_get_embedded_fw() if the
 passed in device has the "efi-embedded-firmware" device-property bool set
-Skip usermodehelper fallback when "efi-embedded-firmware" device-property
 is set
---
 .../driver-api/firmware/request_firmware.rst  |  66 
 drivers/base/firmware_loader/Makefile |   1 +
 drivers/base/firmware_loader/fallback.h   |  12 ++
 drivers/base/firmware_loader/fallback_efi.c   |  51 ++
 drivers/base/firmware_loader/main.c   |   4 +
 drivers/firmware/efi/Kconfig  |   3 +
 drivers/firmware/efi/Makefile |   1 +
 drivers/firmware/efi/embedded-firmware.c  | 152 ++
 include/linux/efi.h   |   6 +
 include/linux/efi_embedded_fw.h   |  25 +++
 init/main.c   |   3 +
 11 files changed, 324 insertions(+)
 create mode 100644 drivers/base/firmware_loader/fallback_efi.c
 create mode 100644 drivers/firmware/efi/embedded-firmware.c
 create mode 100644 include/linux/efi_embedded_fw.h

diff --git a/Documentation/driver-api/firmware/request_firmware.rst 
b/Documentation/driver-api/firmware/request_firmware.rst
index c8bddbdcfd10..560dfed76e38 100644
--- a/Documentation/driver-api/firmware/request_firmware.rst
+++ b/Documentation/driver-api/firmware/request_firmware.rst
@@ -73,3 +73,69 @@ If something went wrong firmware_request() returns non-ze

[PATCH v4 1/5] efi: Export boot-services code and data as debugfs-blobs

2018-04-26 Thread Hans de Goede
Sometimes it is useful to be able to dump the efi boot-services code and
data. This commit adds these as debugfs-blobs to /sys/kernel/debug/efi,
but only if efi=debug is passed on the kernel-commandline as this requires
not freeing those memory-regions, which costs 20+ MB of RAM.

Reviewed-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
Changes in v4:
-Add new EFI_BOOT_SERVICES flag and use it to determine if the boot-services
 memory segments are available (and thus if it makes sense to register the
 debugfs bits for them)

Changes in v2:
-Do not call pr_err on debugfs call failures
---
 arch/x86/platform/efi/efi.c|  1 +
 arch/x86/platform/efi/quirks.c |  4 +++
 drivers/firmware/efi/efi.c | 53 ++
 include/linux/efi.h|  1 +
 4 files changed, 59 insertions(+)

diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 9061babfbc83..568b7ee3d323 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -208,6 +208,7 @@ int __init efi_memblock_x86_reserve_range(void)
 efi.memmap.desc_version);
 
memblock_reserve(pmap, efi.memmap.nr_map * efi.memmap.desc_size);
+   set_bit(EFI_BOOT_SERVICES, );
 
return 0;
 }
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 36c1f8b9f7e0..16bdb9e3b343 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -376,6 +376,10 @@ void __init efi_free_boot_services(void)
int num_entries = 0;
void *new, *new_md;
 
+   /* Keep all regions for /sys/kernel/debug/efi */
+   if (efi_enabled(EFI_DBG))
+   return;
+
for_each_efi_memory_desc(md) {
unsigned long long start = md->phys_addr;
unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 232f4915223b..498a720a7684 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -325,6 +326,55 @@ static __init int efivar_ssdt_load(void)
 static inline int efivar_ssdt_load(void) { return 0; }
 #endif
 
+#ifdef CONFIG_DEBUG_FS
+
+#define EFI_DEBUGFS_MAX_BLOBS 32
+
+static struct debugfs_blob_wrapper debugfs_blob[EFI_DEBUGFS_MAX_BLOBS];
+
+static void __init efi_debugfs_init(void)
+{
+   struct dentry *efi_debugfs;
+   efi_memory_desc_t *md;
+   char name[32];
+   int type_count[EFI_BOOT_SERVICES_DATA + 1] = {};
+   int i = 0;
+
+   efi_debugfs = debugfs_create_dir("efi", NULL);
+   if (IS_ERR_OR_NULL(efi_debugfs))
+   return;
+
+   for_each_efi_memory_desc(md) {
+   switch (md->type) {
+   case EFI_BOOT_SERVICES_CODE:
+   snprintf(name, sizeof(name), "boot_services_code%d",
+type_count[md->type]++);
+   break;
+   case EFI_BOOT_SERVICES_DATA:
+   snprintf(name, sizeof(name), "boot_services_data%d",
+type_count[md->type]++);
+   break;
+   default:
+   continue;
+   }
+
+   debugfs_blob[i].size = md->num_pages << EFI_PAGE_SHIFT;
+   debugfs_blob[i].data = memremap(md->phys_addr,
+   debugfs_blob[i].size,
+   MEMREMAP_WB);
+   if (!debugfs_blob[i].data)
+   continue;
+
+   debugfs_create_blob(name, 0400, efi_debugfs, _blob[i]);
+   i++;
+   if (i == EFI_DEBUGFS_MAX_BLOBS)
+   break;
+   }
+}
+#else
+static inline void efi_debugfs_init(void) {}
+#endif
+
 /*
  * We register the efi subsystem with the firmware subsystem and the
  * efivars subsystem with the efi subsystem, if the system was booted with
@@ -369,6 +419,9 @@ static int __init efisubsys_init(void)
goto err_remove_group;
}
 
+   if (efi_enabled(EFI_DBG) && efi_enabled(EFI_BOOT_SERVICES))
+   efi_debugfs_init();
+
return 0;
 
 err_remove_group:
diff --git a/include/linux/efi.h b/include/linux/efi.h
index f1b7d68ac460..396bf18ace5c 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1144,6 +1144,7 @@ extern int __init efi_setup_pcdp_console(char *);
 #define EFI_DBG8   /* Print additional debug info 
at runtime */
 #define EFI_NX_PE_DATA 9   /* Can runtime data regions be mapped 
non-executable? */
 #define EFI_MEM_ATTR   10  /* Did firmware publish an 
EFI_MEMORY_ATTRIBUTES table? */
+#define EFI_BOOT_SERVICES  11  /* Are E

[PATCH v4 4/5] platform/x86: touchscreen_dmi: Add EFI embedded firmware info support

2018-04-26 Thread Hans de Goede
Sofar we have been unable to get permission from the vendors to put the
firmware for touchscreens listed in touchscreen_dmi in linux-firmware.

Some of the tablets with such a touchscreen have a touchscreen driver, and
thus a copy of the firmware, as part of their EFI code.

This commit adds the necessary info for the new EFI embedded-firmware code
to extract these firmwares, making the touchscreen work OOTB without the
user needing to manually add the firmware.

Acked-by: Andy Shevchenko <andy.shevche...@gmail.com>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 drivers/firmware/efi/embedded-firmware.c |  3 +++
 drivers/platform/x86/Kconfig |  1 +
 drivers/platform/x86/touchscreen_dmi.c   | 26 +++-
 include/linux/efi_embedded_fw.h  |  2 ++
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/embedded-firmware.c 
b/drivers/firmware/efi/embedded-firmware.c
index ef6282945307..bbc6d218a82d 100644
--- a/drivers/firmware/efi/embedded-firmware.c
+++ b/drivers/firmware/efi/embedded-firmware.c
@@ -23,6 +23,9 @@ struct embedded_fw {
 static LIST_HEAD(found_fw_list);
 
 static const struct dmi_system_id * const embedded_fw_table[] = {
+#ifdef CONFIG_TOUCHSCREEN_DMI
+   touchscreen_dmi_table,
+#endif
NULL
 };
 
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 7ff206e5edfe..cc4d95459190 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1199,6 +1199,7 @@ config INTEL_TURBO_MAX_3
 config TOUCHSCREEN_DMI
bool "DMI based touchscreen configuration info"
depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD
+   select EFI_EMBEDDED_FIRMWARE if EFI
---help---
  Certain ACPI based tablets with e.g. Silead or Chipone touchscreens
  do not have enough data in ACPI tables for the touchscreen driver to
diff --git a/drivers/platform/x86/touchscreen_dmi.c 
b/drivers/platform/x86/touchscreen_dmi.c
index 87fc839b28f7..6488cd50ba79 100644
--- a/drivers/platform/x86/touchscreen_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -15,12 +15,15 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 
 struct ts_dmi_data {
+   /* The EFI embedded-fw code expects this to be the first member! */
+   struct efi_embedded_fw_desc embedded_fw;
const char *acpi_name;
const struct property_entry *properties;
 };
@@ -31,10 +34,17 @@ static const struct property_entry cube_iwork8_air_props[] 
= {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
{ }
 };
 
 static const struct ts_dmi_data cube_iwork8_air_data = {
+   .embedded_fw = {
+   .name   = "silead/gsl3670-cube-iwork8-air.fw",
+   .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+   .length = 38808,
+   .crc= 0xfecde51f,
+   },
.acpi_name  = "MSSL1680:00",
.properties = cube_iwork8_air_props,
 };
@@ -119,10 +129,17 @@ static const struct property_entry pipo_w2s_props[] = {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name",
  "gsl1680-pipo-w2s.fw"),
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
{ }
 };
 
 static const struct ts_dmi_data pipo_w2s_data = {
+   .embedded_fw = {
+   .name   = "silead/gsl1680-pipo-w2s.fw",
+   .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+   .length = 39072,
+   .crc= 0x28d5dc6c,
+   },
.acpi_name  = "MSSL1680:00",
.properties = pipo_w2s_props,
 };
@@ -162,10 +179,17 @@ static const struct property_entry chuwi_hi8_pro_props[] 
= {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"),
PROPERTY_ENTRY_BOOL("silead,home-button"),
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
{ }
 };
 
 static const struct ts_dmi_data chuwi_hi8_pro_data = {
+   .embedded_fw = {
+   .name   = "silead/gsl3680-chuwi-hi8-pro.fw",
+   .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+   .length = 39864,
+   .crc= 0xfe2bedba,
+   },
.acpi_name  = "MSSL1680:00",
.properties = chuwi_hi8_pro_props,
 };
@@ -277,7 +301,7 @@ static const struct ts_dmi_data teclast_x3_plus_data = {
.properties = teclast_x3_

[PATCH v4 3/5] platform/x86: Rename silead_dmi to touchscreen_dmi

2018-04-26 Thread Hans de Goede
Not only silead touchscreens need some extra info not available in the
ACPI tables to work properly. X86 devices with a Chipone ICN8505 chip also
need some DMI based extra configuration.

There is no reason to have separate dmi config code per touchscreen
controller vendor. This commit renames silead_dmi to a more generic
touchscreen_dmi name (and Kconfig option) in preparation of adding
info for tablets with an ICN8505 based touchscreen.

Note there are no functional changes all code changes are limited to
removing references to silead where these are no longer applicable.

Acked-by: Andy Shevchenko <andy.shevche...@gmail.com>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 MAINTAINERS   |  2 +-
 drivers/platform/x86/Kconfig  | 16 ++---
 drivers/platform/x86/Makefile |  2 +-
 .../x86/{silead_dmi.c => touchscreen_dmi.c}   | 66 +--
 4 files changed, 43 insertions(+), 43 deletions(-)
 rename drivers/platform/x86/{silead_dmi.c => touchscreen_dmi.c} (87%)

diff --git a/MAINTAINERS b/MAINTAINERS
index bee29977a3bd..5a215bcd6660 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12795,7 +12795,7 @@ L:  linux-in...@vger.kernel.org
 L: platform-driver-...@vger.kernel.org
 S: Maintained
 F: drivers/input/touchscreen/silead.c
-F: drivers/platform/x86/silead_dmi.c
+F: drivers/platform/x86/touchscreen_dmi.c
 
 SILICON MOTION SM712 FRAME BUFFER DRIVER
 M: Sudip Mukherjee <sudipm.mukher...@gmail.com>
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 39d06dd1f63a..7ff206e5edfe 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1196,16 +1196,16 @@ config INTEL_TURBO_MAX_3
  This driver is only required when the system is not using Hardware
  P-States (HWP). In HWP mode, priority can be read from ACPI tables.
 
-config SILEAD_DMI
-   bool "Tablets with Silead touchscreens"
+config TOUCHSCREEN_DMI
+   bool "DMI based touchscreen configuration info"
depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD
---help---
- Certain ACPI based tablets with Silead touchscreens do not have
- enough data in ACPI tables for the touchscreen driver to handle
- the touchscreen properly, as OEMs expected the data to be baked
- into the tablet model specific version of the driver shipped
- with the OS-image for the device. This option supplies the missing
- information. Enable this for x86 tablets with Silead touchscreens.
+ Certain ACPI based tablets with e.g. Silead or Chipone touchscreens
+ do not have enough data in ACPI tables for the touchscreen driver to
+ handle the touchscreen properly, as OEMs expect the data to be baked
+ into the tablet model specific version of the driver shipped with the
+ the OS-image for the device. This option supplies the missing info.
+ Enable this for x86 tablets with Silead or Chipone touchscreens.
 
 config INTEL_CHTDC_TI_PWRBTN
tristate "Intel Cherry Trail Dollar Cove TI power button driver"
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 2ba6cb795338..8d9477114fb5 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -78,7 +78,7 @@ obj-$(CONFIG_INTEL_SMARTCONNECT)  += intel-smartconnect.o
 obj-$(CONFIG_PVPANIC)   += pvpanic.o
 obj-$(CONFIG_ALIENWARE_WMI)+= alienware-wmi.o
 obj-$(CONFIG_INTEL_PMC_IPC)+= intel_pmc_ipc.o
-obj-$(CONFIG_SILEAD_DMI)   += silead_dmi.o
+obj-$(CONFIG_TOUCHSCREEN_DMI)  += touchscreen_dmi.o
 obj-$(CONFIG_SURFACE_PRO3_BUTTON)  += surfacepro3_button.o
 obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o
 obj-$(CONFIG_INTEL_PUNIT_IPC)  += intel_punit_ipc.o
diff --git a/drivers/platform/x86/silead_dmi.c 
b/drivers/platform/x86/touchscreen_dmi.c
similarity index 87%
rename from drivers/platform/x86/silead_dmi.c
rename to drivers/platform/x86/touchscreen_dmi.c
index 452aacabaa8e..87fc839b28f7 100644
--- a/drivers/platform/x86/silead_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -1,5 +1,5 @@
 /*
- * Silead touchscreen driver DMI based configuration code
+ * Touchscreen driver DMI based configuration code
  *
  * Copyright (c) 2017 Red Hat Inc.
  *
@@ -20,7 +20,7 @@
 #include 
 #include 
 
-struct silead_ts_dmi_data {
+struct ts_dmi_data {
const char *acpi_name;
const struct property_entry *properties;
 };
@@ -34,7 +34,7 @@ static const struct property_entry cube_iwork8_air_props[] = {
{ }
 };
 
-static const struct silead_ts_dmi_data cube_iwork8_air_data = {
+static const struct ts_dmi_data cube_iwork8_air_data = {
.acpi_name  = "MSSL1680:00",
.properties = cube_iwork8_air_props,
 };
@@ -48,7 +48,7 @@ static const struct property_entry j

[PATCH v4 5/5] platform/x86: touchscreen_dmi: Add info for the Chuwi Vi8 Plus tablet

2018-04-26 Thread Hans de Goede
Add touchscreen info for the Chuwi Vi8 Plus tablet. This tablet uses a
Chipone ICN8505 touchscreen controller, with the firmware used by the
touchscreen embedded in the EFI firmware.

Acked-by: Andy Shevchenko <andy.shevche...@gmail.com>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 drivers/platform/x86/touchscreen_dmi.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/drivers/platform/x86/touchscreen_dmi.c 
b/drivers/platform/x86/touchscreen_dmi.c
index 6488cd50ba79..5fdb6fe878f4 100644
--- a/drivers/platform/x86/touchscreen_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -301,6 +301,22 @@ static const struct ts_dmi_data teclast_x3_plus_data = {
.properties = teclast_x3_plus_props,
 };
 
+static const struct property_entry efi_embedded_fw_props[] = {
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
+   { }
+};
+
+static const struct ts_dmi_data chuwi_vi8_plus_data = {
+   .embedded_fw = {
+   .name   = "chipone/icn8505-HAMP0002.fw",
+   .prefix = { 0xb0, 0x07, 0x00, 0x00, 0xe4, 0x07, 0x00, 0x00 },
+   .length = 35012,
+   .crc= 0x74dfd3fc,
+   },
+   .acpi_name  = "CHPN0001:00",
+   .properties = efi_embedded_fw_props,
+};
+
 const struct dmi_system_id touchscreen_dmi_table[] = {
{
/* CUBE iwork8 Air */
@@ -487,6 +503,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"),
},
},
+   {
+   /* Chuwi Vi8 Plus (CWI506) */
+   .driver_data = (void *)_vi8_plus_data,
+   .matches = {
+   DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
+   DMI_MATCH(DMI_PRODUCT_NAME, "D2D3_Vi8A1"),
+   DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+   },
+   },
{ },
 };
 
-- 
2.17.0

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 0/5] efi/firmware/platform-x86: Add EFI embedded fw support

2018-04-26 Thread Hans de Goede
Hi All,

Here is v4 of my patch-set to add support for EFI embedded fw to the kernel.

Changes since v3:
-Drop note in docs about EFI_FIRMWARE_VOLUME_PROTOCOL, it is not part of
 UEFI proper, so the EFI maintainers don't want us referring people to it
-Use new EFI_BOOT_SERVICES flag
-Put the new fw_get_efi_embedded_fw() function in its own fallback_efi.c
 file which only gets built when EFI_EMBEDDED_FIRMWARE is selected
-Define an empty stub for fw_get_efi_embedded_fw() in fallback.h hwen
 EFI_EMBEDDED_FIRMWARE is not selected, to avoid the need for #ifdefs
 in firmware_loader/main.c
-Properly call security_kernel_post_read_file() on the firmware returned
 by efi_get_embedded_fw() to make sure that we are allowed to use it

So I think this patch-set is getting close to ready for merging, which
brings us to the question of how to merge this, I think that patches 1
and 2 should probably both be merged through the same tree. Then an
unmutable branch should be created on that tree, merged into the
platform/x86 tree and then the last 3 patches can be merged through
that tree.

For the record, here is the coverletter of v2 of this patchset:

The 3 most prominent changes in v2 are:

1) Add documentation describing the EFI embedded firmware mechanism to:
   Documentation/driver-api/firmware/request_firmware.rst

2) Instead of having a single dmi_system_id array with its driver_data
   members pointing to efi_embedded_fw_desc structs, have the drivers which
   need EFI embedded-fw support export a dmi_system_id array and register
   that with the EFI embedded-fw code

   This series also includes the first driver to use this, in the form of
   the touchscreen_dmi code (formerly silead_dmi) from drivers/platfrom/x86

3) As discussed during the review of v1 we want to make the firmware_loader
   code fallback to EFI embedded-fw optional.  Rather the adding yet another
   firmware_request_foo variant for this, with the risk of later also needing
   firmware_request_foo_nowait, etc. variants I've decided to make the code
   check if the device has a "efi-embedded-firmware" device-property bool set.

   This also seemed better because the same driver may want to use the
   fallback on some systems, but not on others since e.g. not all (x86)
   systems with a silead touchscreen have their touchscreen firmware embedded
   in their EFI.

   Note that (as discussed) when the EFI fallback path is requested, the
   usermodehelper fallback path is skipped.

Here is the full changelog of patch 2/5 which is where most of the changes are:

Changes in v2:
-Rebased on driver-core/driver-core-next
-Add documentation describing the EFI embedded firmware mechanism to:
 Documentation/driver-api/firmware/request_firmware.rst
-Add a new EFI_EMBEDDED_FIRMWARE Kconfig bool and only build the embedded
 fw support if this is set. This is an invisible option which should be
 selected by drivers which need this
-Remove the efi_embedded_fw_desc and dmi_system_id-s for known devices
 from the efi-embedded-fw code, instead drivers using this are expected to
 export a dmi_system_id array, with each entries' driver_data pointing to a
 efi_embedded_fw_desc struct and register this with the efi-embedded-fw code
-Use kmemdup to make a copy instead of efi_mem_reserve()-ing the firmware,
 this avoids us messing with the EFI memmap and avoids the need to make
 changes to efi_mem_desc_lookup()
-Make the firmware-loader code only fallback to efi_get_embedded_fw() if the
 passed in device has the "efi-embedded-firmware" device-property bool set
-Skip usermodehelper fallback when "efi-embedded-firmware" device-property
 is set

Patches 3-5 are new and implement using the EFI embedded-fw mechanism for
Silead gsl and Chipone icn8505 touchscreens on x86 devices.

Regards,

Hans

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 2/5] efi: Add embedded peripheral firmware support

2018-04-24 Thread Hans de Goede

Hi,

On 24-04-18 18:07, Mimi Zohar wrote:

On Tue, 2018-04-24 at 17:09 +0200, Hans de Goede wrote:

Hi,

On 23-04-18 23:11, Luis R. Rodriguez wrote:

Hans, please see use of READING_FIRMWARE_PREALLOC_BUFFER, we'll need a new ID
and security for this type of request so IMA can reject it if the policy is
configured for it.


Hmm, interesting, actually it seems like the whole existence
of READING_FIRMWARE_PREALLOC_BUFFER is a mistake, the IMA
framework really does not care if we are loading the firmware
into memory allocated by the firmware-loader code, or into
memory allocated by the device-driver requesting the firmware.

As such the current IMA code (from v4.17-rc2) actually does
not handle READING_FIRMWARE_PREALLOC_BUFFER at all,


Right, it doesn't yet address READING_FIRMWARE_PREALLOC_BUFFER, but
should.

Depending on whether the device requesting the firmware has access to
the DMA memory, before the signature verification, will determine how
IMA-appraisal addresses READING_FIRMWARE_PREALLOC_BUFFER.


Ah I see. So this probably means that the IMA integration for
my EFI embedded firmware code should also pass READING_FIRMWARE or
READING_FIRMWARE_PREALLOC_BUFFER depending on if a pre-allocated
buffer is used.

Hmm, the security_kernel_post_read_file() call in
drivers/base/firmware_loader/fallback.c

Unconditionally passes READING_FIRMWARE, it should probably check
fw_priv->is_paged_buf and base the id to pass on that.

And yes it is possible AFAICT for the firmware_request_into_buf()
method to fallback to the userspace helper, this can happen if the
fw_fallback_config.force_sysfs_fallback flag is set.

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 2/5] efi: Add embedded peripheral firmware support

2018-04-24 Thread Hans de Goede

Hi,

On 23-04-18 23:11, Luis R. Rodriguez wrote:

Hans, please see use of READING_FIRMWARE_PREALLOC_BUFFER, we'll need a new ID
and security for this type of request so IMA can reject it if the policy is
configured for it.


Hmm, interesting, actually it seems like the whole existence
of READING_FIRMWARE_PREALLOC_BUFFER is a mistake, the IMA
framework really does not care if we are loading the firmware
into memory allocated by the firmware-loader code, or into
memory allocated by the device-driver requesting the firmware.

As such the current IMA code (from v4.17-rc2) actually does
not handle READING_FIRMWARE_PREALLOC_BUFFER at all, here
are bits of code from: security/integrity/ima/ima_main.c:

static int read_idmap[READING_MAX_ID] = {
[READING_FIRMWARE] = FIRMWARE_CHECK,
[READING_MODULE] = MODULE_CHECK,
[READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK,
[READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK,
[READING_POLICY] = POLICY_CHECK
};

int ima_post_read_file(struct file *file, void *buf, loff_t size,
...
if (!file && read_id == READING_FIRMWARE) {
if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
(ima_appraise & IMA_APPRAISE_ENFORCE))
return -EACCES; /* INTEGRITY_UNKNOWN */
return 0;
}

Which show that the IMA code is not handling
READING_FIRMWARE_PREALLOC_BUFFER as it should (I believe it
should handle it the same as READING_FIRMWARE).

Now we could fix that, but the only user of
READING_FIRMWARE_PREALLOC_BUFFER is the code which originally
introduced it:

https://patchwork.kernel.org/patch/9162011/

So I believe it might be better to instead replace it
with just READING_FIRMWARE and find another way to tell
kernel_read_file() that there is a pre-allocated buffer,
perhaps the easiest way there is that  *buf must be
NULL when the caller wants kernel_read_file() to
vmalloc the mem. This would of course require auditing
all callers that the buf which the pass in is initialized
to NULL.

Either way adding a third READING_FIRMWARE_FOO to the
kernel_read_file_id enum seems like a bad idea, from
the IMA pov firmware is firmware.

What this whole exercise has shown me though is that
I need to call security_kernel_post_read_file() when
loading EFI embedded firmware. I will add a call to
security_kernel_post_read_file() for v4 of the patch-set.


Please Cc Kees in future patches.


Will do.

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 2/5] efi: Add embedded peripheral firmware support

2018-04-24 Thread Hans de Goede

Hi,

On 16-04-18 10:28, Ard Biesheuvel wrote:

On 8 April 2018 at 19:40, Hans de Goede <hdego...@redhat.com> wrote:

Just like with PCI options ROMs, which we save in the setup_efi_pci*
functions from arch/x86/boot/compressed/eboot.c, the EFI code / ROM itself
sometimes may contain data which is useful/necessary for peripheral drivers
to have access to.

Specifically the EFI code may contain an embedded copy of firmware which
needs to be (re)loaded into the peripheral. Normally such firmware would be
part of linux-firmware, but in some cases this is not feasible, for 2
reasons:

1) The firmware is customized for a specific use-case of the chipset / use
with a specific hardware model, so we cannot have a single firmware file
for the chipset. E.g. touchscreen controller firmwares are compiled
specifically for the hardware model they are used with, as they are
calibrated for a specific model digitizer.

2) Despite repeated attempts we have failed to get permission to
redistribute the firmware. This is especially a problem with customized
firmwares, these get created by the chip vendor for a specific ODM and the
copyright may partially belong with the ODM, so the chip vendor cannot
give a blanket permission to distribute these.

This commit adds support for finding peripheral firmware embedded in the
EFI code and making this available to peripheral drivers through the
standard firmware loading mechanism.

Note we check the EFI_BOOT_SERVICES_CODE for embedded firmware near the end
of start_kernel(), just before calling rest_init(), this is on purpose
because the typical EFI_BOOT_SERVICES_CODE memory-segment is too large for
early_memremap(), so the check must be done after mm_init(). This relies
on EFI_BOOT_SERVICES_CODE not being free-ed until efi_free_boot_services()
is called, which means that this will only work on x86 for now.

Reported-by: Dave Olsthoorn <d...@bewaar.me>
Suggested-by: Peter Jones <pjo...@redhat.com>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
Changes in v2:
-Rebased on driver-core/driver-core-next
-Add documentation describing the EFI embedded firmware mechanism to:
  Documentation/driver-api/firmware/request_firmware.rst
-Add a new EFI_EMBEDDED_FIRMWARE Kconfig bool and only build the embedded
  fw support if this is set. This is an invisible option which should be
  selected by drivers which need this
-Remove the efi_embedded_fw_desc and dmi_system_id-s for known devices
  from the efi-embedded-fw code, instead drivers using this are expected to
  export a dmi_system_id array, with each entries' driver_data pointing to a
  efi_embedded_fw_desc struct and register this with the efi-embedded-fw code
-Use kmemdup to make a copy instead of efi_mem_reserve()-ing the firmware,
  this avoids us messing with the EFI memmap and avoids the need to make
  changes to efi_mem_desc_lookup()
-Make the firmware-loader code only fallback to efi_get_embedded_fw() if the
  passed in device has the "efi-embedded-firmware" device-property bool set
-Skip usermodehelper fallback when "efi-embedded-firmware" device-property
  is set

Changes in v3:
-Fix the docs using "efi-embedded-fw" as property name instead of
  "efi-embedded-firmware"
---
  .../driver-api/firmware/request_firmware.rst  |  70 +
  drivers/base/firmware_loader/main.c   |  33 
  drivers/firmware/efi/Kconfig  |   6 +
  drivers/firmware/efi/Makefile |   1 +
  drivers/firmware/efi/embedded-firmware.c  | 148 ++
  include/linux/efi.h   |   6 +
  include/linux/efi_embedded_fw.h   |  25 +++
  init/main.c   |   1 +
  8 files changed, 290 insertions(+)
  create mode 100644 drivers/firmware/efi/embedded-firmware.c
  create mode 100644 include/linux/efi_embedded_fw.h

diff --git a/Documentation/driver-api/firmware/request_firmware.rst 
b/Documentation/driver-api/firmware/request_firmware.rst
index 20f21ed427a5..189b02f815c9 100644
--- a/Documentation/driver-api/firmware/request_firmware.rst
+++ b/Documentation/driver-api/firmware/request_firmware.rst
@@ -68,3 +68,73 @@ If something went wrong request_firmware() returns non-zero 
and fw_entry
  is set to NULL. Once your driver is done with processing the firmware it
  can call call release_firmware(fw_entry) to release the firmware image
  and any related resource.
+
+EFI embedded firmware support
+=
+
+On some devices the system's EFI code / ROM may contain an embedded copy
+of firmware for some of the system's integrated peripheral devices and
+the peripheral's Linux device-driver needs to access this firmware.
+
+A device driver which needs this can describe the firmware it needs
+using an efi_embedded_fw_desc struct:
+
+.. kernel-doc:: include/linux/efi_embedded_fw.h
+   :functions: efi_embedded_fw_desc
+
+The EFI embedded-fw code works by scanning all EF

Re: [PATCH v3 1/5] efi: Export boot-services code and data as debugfs-blobs

2018-04-24 Thread Hans de Goede

Hi,

On 16-04-18 10:23, Ard Biesheuvel wrote:

Hallo Hans,

On 8 April 2018 at 19:40, Hans de Goede <hdego...@redhat.com> wrote:

Sometimes it is useful to be able to dump the efi boot-services code and
data. This commit adds these as debugfs-blobs to /sys/kernel/debug/efi,
but only if efi=debug is passed on the kernel-commandline as this requires
not freeing those memory-regions, which costs 20+ MB of RAM.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
Changes in v2:
-Do not call pr_err on debugfs call failures
---
  arch/x86/platform/efi/quirks.c |  4 +++
  drivers/firmware/efi/efi.c | 53 ++
  2 files changed, 57 insertions(+)

diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 5b513ccffde4..0f968c7bcfec 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -374,6 +374,10 @@ void __init efi_free_boot_services(void)
 int num_entries = 0;
 void *new, *new_md;

+   /* Keep all regions for /sys/kernel/debug/efi */
+   if (efi_enabled(EFI_DBG))
+   return;
+
 for_each_efi_memory_desc(md) {
 unsigned long long start = md->phys_addr;
 unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index cd42f66a7c85..10c896e8b82b 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -18,6 +18,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -316,6 +317,55 @@ static __init int efivar_ssdt_load(void)
  static inline int efivar_ssdt_load(void) { return 0; }
  #endif

+#ifdef CONFIG_DEBUG_FS
+
+#define EFI_DEBUGFS_MAX_BLOBS 32
+
+static struct debugfs_blob_wrapper debugfs_blob[EFI_DEBUGFS_MAX_BLOBS];
+
+static void __init efi_debugfs_init(void)
+{
+   struct dentry *efi_debugfs;
+   efi_memory_desc_t *md;
+   char name[32];
+   int type_count[EFI_BOOT_SERVICES_DATA + 1] = {};
+   int i = 0;
+
+   efi_debugfs = debugfs_create_dir("efi", NULL);
+   if (IS_ERR_OR_NULL(efi_debugfs))
+   return;
+
+   for_each_efi_memory_desc(md) {
+   switch (md->type) {
+   case EFI_BOOT_SERVICES_CODE:
+   snprintf(name, sizeof(name), "boot_services_code%d",
+type_count[md->type]++);
+   break;
+   case EFI_BOOT_SERVICES_DATA:
+   snprintf(name, sizeof(name), "boot_services_data%d",
+type_count[md->type]++);
+   break;
+   default:
+   continue;
+   }
+
+   debugfs_blob[i].size = md->num_pages << EFI_PAGE_SHIFT;
+   debugfs_blob[i].data = memremap(md->phys_addr,
+   debugfs_blob[i].size,
+   MEMREMAP_WB);
+   if (!debugfs_blob[i].data)
+   continue;
+
+   debugfs_create_blob(name, 0400, efi_debugfs, _blob[i]);
+   i++;
+   if (i == EFI_DEBUGFS_MAX_BLOBS)
+   break;
+   }
+}
+#else
+static inline void efi_debugfs_init(void) {}
+#endif
+
  /*
   * We register the efi subsystem with the firmware subsystem and the
   * efivars subsystem with the efi subsystem, if the system was booted with
@@ -360,6 +410,9 @@ static int __init efisubsys_init(void)
 goto err_remove_group;
 }

+   if (efi_enabled(EFI_DBG))
+   efi_debugfs_init();
+


This doesn't really make any sense on non-x86. The boot services
regions are released to the kernel for general allocation, and so
exposing them this way only makes sense if you keep them as you do for
x86.

Could you please try to make this call specific to situations where it
makes sense? I don't mind allocating a new EFI_xxx flag for preserving
the boot services regions so we could decide to set it for ARM/arm64
as well in certain cases in the future.


Ok, I've added a new EFI_BOOT_SERVICES flag for this for v4 of this
patchset, mirroring the existing EFI_RUNTIME_SERVICES flag in naming.

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 2/5] efi: Add embedded peripheral firmware support

2018-04-17 Thread Hans de Goede

Hi,

On 17-04-18 02:17, Luis R. Rodriguez wrote:

On Sun, Apr 08, 2018 at 07:40:11PM +0200, Hans de Goede wrote:

  static void firmware_free_data(const struct firmware *fw)
  {
@@ -576,6 +600,15 @@ _request_firmware(const struct firmware **firmware_p, 
const char *name,
goto out;
  
  	ret = fw_get_filesystem_firmware(device, fw->priv);

+#ifdef CONFIG_EFI_EMBEDDED_FIRMWARE
+   if (ret && device &&
+   device_property_read_bool(device, "efi-embedded-firmware")) {
+   ret = fw_get_efi_embedded_fw(device, fw->priv, ret);
+   if (ret == 0)
+   ret = assign_fw(fw, device, opt_flags | FW_OPT_NOCACHE);
+   goto out;
+   }
+#endif




So thinking some more about this, I can put the device_property check
inside the fw_get_efi_embedded_fw() call, as well as modify opt_flags
there to or in FW_OPT_NOCACHE on success, then together with the discussed
changed to drop the #ifdef, the code would look like this:

ret = fw_get_filesystem_firmware(device, fw->priv);
if (ret)
fw_get_efi_embedded_fw(device, fw->priv, _flags, ret);
if (ret)
if (!(opt_flags & FW_OPT_NO_WARN))
dev_warn(device,
...

With just these 2 lines being new:

if (ret)
fw_get_efi_embedded_fw(device, fw->priv, _flags, ret);

So the main.c changes will be nice and clean then.

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 2/5] efi: Add embedded peripheral firmware support

2018-04-17 Thread Hans de Goede

Hi,

On 17-04-18 02:17, Luis R. Rodriguez wrote:

On Sun, Apr 08, 2018 at 07:40:11PM +0200, Hans de Goede wrote:

  static void firmware_free_data(const struct firmware *fw)
  {
@@ -576,6 +600,15 @@ _request_firmware(const struct firmware **firmware_p, 
const char *name,
goto out;
  
  	ret = fw_get_filesystem_firmware(device, fw->priv);

+#ifdef CONFIG_EFI_EMBEDDED_FIRMWARE
+   if (ret && device &&
+   device_property_read_bool(device, "efi-embedded-firmware")) {
+   ret = fw_get_efi_embedded_fw(device, fw->priv, ret);
+   if (ret == 0)
+   ret = assign_fw(fw, device, opt_flags | FW_OPT_NOCACHE);
+   goto out;
+   }
+#endif


You mussed what I asked for in terms of adding a new flag, (please work on top
of Andre's patches as those likely will be merged first, and also have kdocs
for the flags)


Ok I will base my next version on top of Andres' series.


and then a new firmware API to wrap the above into a function
which would only do something if the driver *asked* for it on their firmware
API call.
Ie, please add a new firmware_request_efi_fw().


As I tried to explain in the changelog the problem with doing this, is that
this makes it a driver decision, where it really needs to be platform-code 
driven,
not driver driven.

Take for example the drivers/input/touchscreen/silead.c code that is used on
a lot of 32 bit ARM platforms too, which don't have EFI at all, so if that
needs to call request_firmware_efi() then should I add:

#ifdef CONFIG_X86
fw = request_firmware_efi(...);
#else
fw = request_firmware(...);
#endif

? But even on x86 only some devices with a silead touchscreen have EFI
embedded firmware, so then I would need something like:

#ifdef CONFIG_X86
if (device_property_get_bool(dev, "some-prop-name"))
fw = request_firmware_efi(...);
else
#else
fw = request_firmware(...);
#endif

That is assuming I still want the normal fallback path in the
case no EFI firmware is available, which I do because then
something like packagekit may see if the firmware is packaged
in one of the configured distro repositories.

We already have (x86) platform code in place to attach
properties (like a board specific firmware filename) to the
device using device-properties so that drivers like silead.c
don't get filled / polluted with board/platform specific knowledge,
which IMHO is the place where the knowledge fallback to
an EFI embedded firmware copy belongs.

As the further patches in v3 of this series shows, this actually
works quite nicely, because this also allows bundling the
EFI-embedded firmware info (prefix, length, crc, name) together
with the other board specific properties.

TL;DR: using request_firmware_efi() vs request_firmware() is
a driver decision, but whether EFI firmware fallback should be
is board/platform specific not driver specific, therefor I
believe that using a device-property to signal this is better.


If you insist on me adding a request_firmware_efi() I can give
this a shot, but I know that Dmitry (the input maintainer) will
very much dislike the silead.c changes that implies...

Still a question for lets sat we go that route, what do we
then do with request_firmware_efi() when CONFIG_EFI is not set ?
Should it be defined then or not, and if it should be defined
when CONFIG_EFI is not set what should it do then?


Also if you see the
work I've done to remove the ifdefs over fallback mechanism you'll see it helps
split code and make it easier to read. We should strive to not add any more
ifdefery and instead make tehis code read easily.


So looking at how the CONFIG_FW_LOADER_USER_HELPER stuff deals
with this, I should:

1) Move the definition of fw_get_efi_embedded_fw() to a new
drivers/base/firmware_loader/fallback_efi.c,
which only gets build if CONFIG_EFI_EMBEDDED_FIRMWARE is set

2) Put the following in fallback.h:

#ifdef CONFIG_EFI_EMBEDDED_FIRMWARE
int fw_get_efi_embedded_fw(struct device *dev, struct fw_priv *fw_priv, int 
ret);
#else
static inline int
fw_get_efi_embedded_fw(struct device *dev, struct fw_priv *fw_priv, int ret)
{
return ret;
}
#endif

have I got that right?

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 1/5] efi: Export boot-services code and data as debugfs-blobs

2018-04-08 Thread Hans de Goede
Sometimes it is useful to be able to dump the efi boot-services code and
data. This commit adds these as debugfs-blobs to /sys/kernel/debug/efi,
but only if efi=debug is passed on the kernel-commandline as this requires
not freeing those memory-regions, which costs 20+ MB of RAM.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
Changes in v2:
-Do not call pr_err on debugfs call failures
---
 arch/x86/platform/efi/quirks.c |  4 +++
 drivers/firmware/efi/efi.c | 53 ++
 2 files changed, 57 insertions(+)

diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 5b513ccffde4..0f968c7bcfec 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -374,6 +374,10 @@ void __init efi_free_boot_services(void)
int num_entries = 0;
void *new, *new_md;
 
+   /* Keep all regions for /sys/kernel/debug/efi */
+   if (efi_enabled(EFI_DBG))
+   return;
+
for_each_efi_memory_desc(md) {
unsigned long long start = md->phys_addr;
unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index cd42f66a7c85..10c896e8b82b 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -316,6 +317,55 @@ static __init int efivar_ssdt_load(void)
 static inline int efivar_ssdt_load(void) { return 0; }
 #endif
 
+#ifdef CONFIG_DEBUG_FS
+
+#define EFI_DEBUGFS_MAX_BLOBS 32
+
+static struct debugfs_blob_wrapper debugfs_blob[EFI_DEBUGFS_MAX_BLOBS];
+
+static void __init efi_debugfs_init(void)
+{
+   struct dentry *efi_debugfs;
+   efi_memory_desc_t *md;
+   char name[32];
+   int type_count[EFI_BOOT_SERVICES_DATA + 1] = {};
+   int i = 0;
+
+   efi_debugfs = debugfs_create_dir("efi", NULL);
+   if (IS_ERR_OR_NULL(efi_debugfs))
+   return;
+
+   for_each_efi_memory_desc(md) {
+   switch (md->type) {
+   case EFI_BOOT_SERVICES_CODE:
+   snprintf(name, sizeof(name), "boot_services_code%d",
+type_count[md->type]++);
+   break;
+   case EFI_BOOT_SERVICES_DATA:
+   snprintf(name, sizeof(name), "boot_services_data%d",
+type_count[md->type]++);
+   break;
+   default:
+   continue;
+   }
+
+   debugfs_blob[i].size = md->num_pages << EFI_PAGE_SHIFT;
+   debugfs_blob[i].data = memremap(md->phys_addr,
+   debugfs_blob[i].size,
+   MEMREMAP_WB);
+   if (!debugfs_blob[i].data)
+   continue;
+
+   debugfs_create_blob(name, 0400, efi_debugfs, _blob[i]);
+   i++;
+   if (i == EFI_DEBUGFS_MAX_BLOBS)
+   break;
+   }
+}
+#else
+static inline void efi_debugfs_init(void) {}
+#endif
+
 /*
  * We register the efi subsystem with the firmware subsystem and the
  * efivars subsystem with the efi subsystem, if the system was booted with
@@ -360,6 +410,9 @@ static int __init efisubsys_init(void)
goto err_remove_group;
}
 
+   if (efi_enabled(EFI_DBG))
+   efi_debugfs_init();
+
return 0;
 
 err_remove_group:
-- 
2.17.0

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 3/5] platform/x86: Rename silead_dmi to touchscreen_dmi

2018-04-08 Thread Hans de Goede
Not only silead touchscreens need some extra info not available in the
ACPI tables to work properly. X86 devices with a Chipone ICN8505 chip also
need some DMI based extra configuration.

There is no reason to have separate dmi config code per touchscreen
controller vendor. This commit renames silead_dmi to a more generic
touchscreen_dmi name (and Kconfig option) in preparation of adding
info for tablets with an ICN8505 based touchscreen.

Note there are no functional changes all code changes are limited to
removing references to silead where these are no longer applicable.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 MAINTAINERS   |  2 +-
 drivers/platform/x86/Kconfig  | 16 ++---
 drivers/platform/x86/Makefile |  2 +-
 .../x86/{silead_dmi.c => touchscreen_dmi.c}   | 66 +--
 4 files changed, 43 insertions(+), 43 deletions(-)
 rename drivers/platform/x86/{silead_dmi.c => touchscreen_dmi.c} (87%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 0d5c55daeeba..99dd47e3b0dd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12618,7 +12618,7 @@ L:  linux-in...@vger.kernel.org
 L: platform-driver-...@vger.kernel.org
 S: Maintained
 F: drivers/input/touchscreen/silead.c
-F: drivers/platform/x86/silead_dmi.c
+F: drivers/platform/x86/touchscreen_dmi.c
 
 SILICON MOTION SM712 FRAME BUFFER DRIVER
 M: Sudip Mukherjee <sudipm.mukher...@gmail.com>
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 1868aab0282a..b836576f0fe4 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1194,16 +1194,16 @@ config INTEL_TURBO_MAX_3
  This driver is only required when the system is not using Hardware
  P-States (HWP). In HWP mode, priority can be read from ACPI tables.
 
-config SILEAD_DMI
-   bool "Tablets with Silead touchscreens"
+config TOUCHSCREEN_DMI
+   bool "DMI based touchscreen configuration info"
depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD
---help---
- Certain ACPI based tablets with Silead touchscreens do not have
- enough data in ACPI tables for the touchscreen driver to handle
- the touchscreen properly, as OEMs expected the data to be baked
- into the tablet model specific version of the driver shipped
- with the OS-image for the device. This option supplies the missing
- information. Enable this for x86 tablets with Silead touchscreens.
+ Certain ACPI based tablets with e.g. Silead or Chipone touchscreens
+ do not have enough data in ACPI tables for the touchscreen driver to
+ handle the touchscreen properly, as OEMs expect the data to be baked
+ into the tablet model specific version of the driver shipped with the
+ the OS-image for the device. This option supplies the missing info.
+ Enable this for x86 tablets with Silead or Chipone touchscreens.
 
 config INTEL_CHTDC_TI_PWRBTN
tristate "Intel Cherry Trail Dollar Cove TI power button driver"
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 2ba6cb795338..8d9477114fb5 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -78,7 +78,7 @@ obj-$(CONFIG_INTEL_SMARTCONNECT)  += intel-smartconnect.o
 obj-$(CONFIG_PVPANIC)   += pvpanic.o
 obj-$(CONFIG_ALIENWARE_WMI)+= alienware-wmi.o
 obj-$(CONFIG_INTEL_PMC_IPC)+= intel_pmc_ipc.o
-obj-$(CONFIG_SILEAD_DMI)   += silead_dmi.o
+obj-$(CONFIG_TOUCHSCREEN_DMI)  += touchscreen_dmi.o
 obj-$(CONFIG_SURFACE_PRO3_BUTTON)  += surfacepro3_button.o
 obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o
 obj-$(CONFIG_INTEL_PUNIT_IPC)  += intel_punit_ipc.o
diff --git a/drivers/platform/x86/silead_dmi.c 
b/drivers/platform/x86/touchscreen_dmi.c
similarity index 87%
rename from drivers/platform/x86/silead_dmi.c
rename to drivers/platform/x86/touchscreen_dmi.c
index 452aacabaa8e..87fc839b28f7 100644
--- a/drivers/platform/x86/silead_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -1,5 +1,5 @@
 /*
- * Silead touchscreen driver DMI based configuration code
+ * Touchscreen driver DMI based configuration code
  *
  * Copyright (c) 2017 Red Hat Inc.
  *
@@ -20,7 +20,7 @@
 #include 
 #include 
 
-struct silead_ts_dmi_data {
+struct ts_dmi_data {
const char *acpi_name;
const struct property_entry *properties;
 };
@@ -34,7 +34,7 @@ static const struct property_entry cube_iwork8_air_props[] = {
{ }
 };
 
-static const struct silead_ts_dmi_data cube_iwork8_air_data = {
+static const struct ts_dmi_data cube_iwork8_air_data = {
.acpi_name  = "MSSL1680:00",
.properties = cube_iwork8_air_props,
 };
@@ -48,7 +48,7 @@ static const struct property_entry jumper_ezpad_mini3_props[] 
= {
{ }
 };
 
-static const stru

[PATCH v3 2/5] efi: Add embedded peripheral firmware support

2018-04-08 Thread Hans de Goede
Just like with PCI options ROMs, which we save in the setup_efi_pci*
functions from arch/x86/boot/compressed/eboot.c, the EFI code / ROM itself
sometimes may contain data which is useful/necessary for peripheral drivers
to have access to.

Specifically the EFI code may contain an embedded copy of firmware which
needs to be (re)loaded into the peripheral. Normally such firmware would be
part of linux-firmware, but in some cases this is not feasible, for 2
reasons:

1) The firmware is customized for a specific use-case of the chipset / use
with a specific hardware model, so we cannot have a single firmware file
for the chipset. E.g. touchscreen controller firmwares are compiled
specifically for the hardware model they are used with, as they are
calibrated for a specific model digitizer.

2) Despite repeated attempts we have failed to get permission to
redistribute the firmware. This is especially a problem with customized
firmwares, these get created by the chip vendor for a specific ODM and the
copyright may partially belong with the ODM, so the chip vendor cannot
give a blanket permission to distribute these.

This commit adds support for finding peripheral firmware embedded in the
EFI code and making this available to peripheral drivers through the
standard firmware loading mechanism.

Note we check the EFI_BOOT_SERVICES_CODE for embedded firmware near the end
of start_kernel(), just before calling rest_init(), this is on purpose
because the typical EFI_BOOT_SERVICES_CODE memory-segment is too large for
early_memremap(), so the check must be done after mm_init(). This relies
on EFI_BOOT_SERVICES_CODE not being free-ed until efi_free_boot_services()
is called, which means that this will only work on x86 for now.

Reported-by: Dave Olsthoorn <d...@bewaar.me>
Suggested-by: Peter Jones <pjo...@redhat.com>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
Changes in v2:
-Rebased on driver-core/driver-core-next
-Add documentation describing the EFI embedded firmware mechanism to:
 Documentation/driver-api/firmware/request_firmware.rst
-Add a new EFI_EMBEDDED_FIRMWARE Kconfig bool and only build the embedded
 fw support if this is set. This is an invisible option which should be
 selected by drivers which need this
-Remove the efi_embedded_fw_desc and dmi_system_id-s for known devices
 from the efi-embedded-fw code, instead drivers using this are expected to
 export a dmi_system_id array, with each entries' driver_data pointing to a
 efi_embedded_fw_desc struct and register this with the efi-embedded-fw code
-Use kmemdup to make a copy instead of efi_mem_reserve()-ing the firmware,
 this avoids us messing with the EFI memmap and avoids the need to make
 changes to efi_mem_desc_lookup()
-Make the firmware-loader code only fallback to efi_get_embedded_fw() if the
 passed in device has the "efi-embedded-firmware" device-property bool set
-Skip usermodehelper fallback when "efi-embedded-firmware" device-property
 is set

Changes in v3:
-Fix the docs using "efi-embedded-fw" as property name instead of
 "efi-embedded-firmware"
---
 .../driver-api/firmware/request_firmware.rst  |  70 +
 drivers/base/firmware_loader/main.c   |  33 
 drivers/firmware/efi/Kconfig  |   6 +
 drivers/firmware/efi/Makefile |   1 +
 drivers/firmware/efi/embedded-firmware.c  | 148 ++
 include/linux/efi.h   |   6 +
 include/linux/efi_embedded_fw.h   |  25 +++
 init/main.c   |   1 +
 8 files changed, 290 insertions(+)
 create mode 100644 drivers/firmware/efi/embedded-firmware.c
 create mode 100644 include/linux/efi_embedded_fw.h

diff --git a/Documentation/driver-api/firmware/request_firmware.rst 
b/Documentation/driver-api/firmware/request_firmware.rst
index 20f21ed427a5..189b02f815c9 100644
--- a/Documentation/driver-api/firmware/request_firmware.rst
+++ b/Documentation/driver-api/firmware/request_firmware.rst
@@ -68,3 +68,73 @@ If something went wrong request_firmware() returns non-zero 
and fw_entry
 is set to NULL. Once your driver is done with processing the firmware it
 can call call release_firmware(fw_entry) to release the firmware image
 and any related resource.
+
+EFI embedded firmware support
+=
+
+On some devices the system's EFI code / ROM may contain an embedded copy
+of firmware for some of the system's integrated peripheral devices and
+the peripheral's Linux device-driver needs to access this firmware.
+
+A device driver which needs this can describe the firmware it needs
+using an efi_embedded_fw_desc struct:
+
+.. kernel-doc:: include/linux/efi_embedded_fw.h
+   :functions: efi_embedded_fw_desc
+
+The EFI embedded-fw code works by scanning all EFI_BOOT_SERVICES_CODE memory
+segments for an eight byte sequence matching prefix, if the prefix is found it
+then does a crc32 over length bytes 

[PATCH v3 0/5] efi/firmware/platform-x86: Add EFI embedded fw support

2018-04-08 Thread Hans de Goede
Hi All,

Sorry for sending a v3 so soon after v2, I got the property name wrong in the
documentation added in v2 and of course noticed that minutes after sending v2.
This version fixes this.

Here is the v2 coverletter again:

Here is v2 of my patch-set to add support for EFI embedded fw to the kernel.

The 3 most prominent changes are:

1) Add documentation describing the EFI embedded firmware mechanism to:
   Documentation/driver-api/firmware/request_firmware.rst

2) Instead of having a single dmi_system_id array with its driver_data
   members pointing to efi_embedded_fw_desc structs, have the drivers which
   need EFI embedded-fw support export a dmi_system_id array and register
   that with the EFI embedded-fw code

   This series also includes the first driver to use this, in the form of
   the touchscreen_dmi code (formerly silead_dmi) from drivers/platfrom/x86

3) As discussed during the review of v1 we want to make the firmware_loader
   code fallback to EFI embedded-fw optional.  Rather the adding yet another
   firmware_request_foo variant for this, with the risk of later also needing
   firmware_request_foo_nowait, etc. variants I've decided to make the code
   check if the device has a "efi-embedded-firmware" device-property bool set.

   This also seemed better because the same driver may want to use the
   fallback on some systems, but not on others since e.g. not all (x86)
   systems with a silead touchscreen have their touchscreen firmware embedded
   in their EFI.

   Note that (as discussed) when the EFI fallback path is requested, the
   usermodehelper fallback path is skipped.

Here is the full changelog of patch 2/5 which is where most of the changes are:

Changes in v2:
-Rebased on driver-core/driver-core-next
-Add documentation describing the EFI embedded firmware mechanism to:
 Documentation/driver-api/firmware/request_firmware.rst
-Add a new EFI_EMBEDDED_FIRMWARE Kconfig bool and only build the embedded
 fw support if this is set. This is an invisible option which should be
 selected by drivers which need this
-Remove the efi_embedded_fw_desc and dmi_system_id-s for known devices
 from the efi-embedded-fw code, instead drivers using this are expected to
 export a dmi_system_id array, with each entries' driver_data pointing to a
 efi_embedded_fw_desc struct and register this with the efi-embedded-fw code
-Use kmemdup to make a copy instead of efi_mem_reserve()-ing the firmware,
 this avoids us messing with the EFI memmap and avoids the need to make
 changes to efi_mem_desc_lookup()
-Make the firmware-loader code only fallback to efi_get_embedded_fw() if the
 passed in device has the "efi-embedded-firmware" device-property bool set
-Skip usermodehelper fallback when "efi-embedded-firmware" device-property
 is set

Patches 3-5 are new and implement using the EFI embedded-fw mechanism for
Silead gsl and Chipone icn8505 touchscreens on x86 devices.

Regards,

Hans

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 5/5] platform/x86: touchscreen_dmi: Add info for the Chuwi Vi8 Plus tablet

2018-04-08 Thread Hans de Goede
Add touchscreen info for the Chuwi Vi8 Plus tablet. This tablet uses a
Chipone ICN8505 touchscreen controller, with the firmware used by the
touchscreen embedded in the EFI firmware.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 drivers/platform/x86/touchscreen_dmi.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/drivers/platform/x86/touchscreen_dmi.c 
b/drivers/platform/x86/touchscreen_dmi.c
index 6488cd50ba79..5fdb6fe878f4 100644
--- a/drivers/platform/x86/touchscreen_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -301,6 +301,22 @@ static const struct ts_dmi_data teclast_x3_plus_data = {
.properties = teclast_x3_plus_props,
 };
 
+static const struct property_entry efi_embedded_fw_props[] = {
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
+   { }
+};
+
+static const struct ts_dmi_data chuwi_vi8_plus_data = {
+   .embedded_fw = {
+   .name   = "chipone/icn8505-HAMP0002.fw",
+   .prefix = { 0xb0, 0x07, 0x00, 0x00, 0xe4, 0x07, 0x00, 0x00 },
+   .length = 35012,
+   .crc= 0x74dfd3fc,
+   },
+   .acpi_name  = "CHPN0001:00",
+   .properties = efi_embedded_fw_props,
+};
+
 const struct dmi_system_id touchscreen_dmi_table[] = {
{
/* CUBE iwork8 Air */
@@ -487,6 +503,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"),
},
},
+   {
+   /* Chuwi Vi8 Plus (CWI506) */
+   .driver_data = (void *)_vi8_plus_data,
+   .matches = {
+   DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
+   DMI_MATCH(DMI_PRODUCT_NAME, "D2D3_Vi8A1"),
+   DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+   },
+   },
{ },
 };
 
-- 
2.17.0

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 4/5] platform/x86: touchscreen_dmi: Add EFI embedded firmware info support

2018-04-08 Thread Hans de Goede
Sofar we have been unable to get permission from the vendors to put the
firmware for touchscreens listed in touchscreen_dmi in linux-firmware.

Some of the tablets with such a touchscreen have a touchscreen driver, and
thus a copy of the firmware, as part of their EFI code.

This commit adds the necessary info for the new EFI embedded-firmware code
to extract these firmwares, making the touchscreen work OOTB without the
user needing to manually add the firmware.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 drivers/firmware/efi/embedded-firmware.c |  3 +++
 drivers/platform/x86/Kconfig |  1 +
 drivers/platform/x86/touchscreen_dmi.c   | 26 +++-
 include/linux/efi_embedded_fw.h  |  2 ++
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/embedded-firmware.c 
b/drivers/firmware/efi/embedded-firmware.c
index cb57225a340d..26101ac1a282 100644
--- a/drivers/firmware/efi/embedded-firmware.c
+++ b/drivers/firmware/efi/embedded-firmware.c
@@ -23,6 +23,9 @@ struct embedded_fw {
 static LIST_HEAD(found_fw_list);
 
 static const struct dmi_system_id * const embedded_fw_table[] = {
+#ifdef CONFIG_TOUCHSCREEN_DMI
+   touchscreen_dmi_table,
+#endif
NULL
 };
 
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index b836576f0fe4..5bb0f5edd7f2 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1197,6 +1197,7 @@ config INTEL_TURBO_MAX_3
 config TOUCHSCREEN_DMI
bool "DMI based touchscreen configuration info"
depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD
+   select EFI_EMBEDDED_FIRMWARE if EFI_STUB
---help---
  Certain ACPI based tablets with e.g. Silead or Chipone touchscreens
  do not have enough data in ACPI tables for the touchscreen driver to
diff --git a/drivers/platform/x86/touchscreen_dmi.c 
b/drivers/platform/x86/touchscreen_dmi.c
index 87fc839b28f7..6488cd50ba79 100644
--- a/drivers/platform/x86/touchscreen_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -15,12 +15,15 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 
 struct ts_dmi_data {
+   /* The EFI embedded-fw code expects this to be the first member! */
+   struct efi_embedded_fw_desc embedded_fw;
const char *acpi_name;
const struct property_entry *properties;
 };
@@ -31,10 +34,17 @@ static const struct property_entry cube_iwork8_air_props[] 
= {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
{ }
 };
 
 static const struct ts_dmi_data cube_iwork8_air_data = {
+   .embedded_fw = {
+   .name   = "silead/gsl3670-cube-iwork8-air.fw",
+   .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+   .length = 38808,
+   .crc= 0xfecde51f,
+   },
.acpi_name  = "MSSL1680:00",
.properties = cube_iwork8_air_props,
 };
@@ -119,10 +129,17 @@ static const struct property_entry pipo_w2s_props[] = {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name",
  "gsl1680-pipo-w2s.fw"),
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
{ }
 };
 
 static const struct ts_dmi_data pipo_w2s_data = {
+   .embedded_fw = {
+   .name   = "silead/gsl1680-pipo-w2s.fw",
+   .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+   .length = 39072,
+   .crc= 0x28d5dc6c,
+   },
.acpi_name  = "MSSL1680:00",
.properties = pipo_w2s_props,
 };
@@ -162,10 +179,17 @@ static const struct property_entry chuwi_hi8_pro_props[] 
= {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"),
PROPERTY_ENTRY_BOOL("silead,home-button"),
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
{ }
 };
 
 static const struct ts_dmi_data chuwi_hi8_pro_data = {
+   .embedded_fw = {
+   .name   = "silead/gsl3680-chuwi-hi8-pro.fw",
+   .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+   .length = 39864,
+   .crc= 0xfe2bedba,
+   },
.acpi_name  = "MSSL1680:00",
.properties = chuwi_hi8_pro_props,
 };
@@ -277,7 +301,7 @@ static const struct ts_dmi_data teclast_x3_plus_data = {
.properties = teclast_x3_plus_props,
 };
 
-static const struct dmi_system_id tou

[PATCH v2 1/5] efi: Export boot-services code and data as debugfs-blobs

2018-04-08 Thread Hans de Goede
Sometimes it is useful to be able to dump the efi boot-services code and
data. This commit adds these as debugfs-blobs to /sys/kernel/debug/efi,
but only if efi=debug is passed on the kernel-commandline as this requires
not freeing those memory-regions, which costs 20+ MB of RAM.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
Changes in v2:
-Do not call pr_err on debugfs call failures
---
 arch/x86/platform/efi/quirks.c |  4 +++
 drivers/firmware/efi/efi.c | 53 ++
 2 files changed, 57 insertions(+)

diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 5b513ccffde4..0f968c7bcfec 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -374,6 +374,10 @@ void __init efi_free_boot_services(void)
int num_entries = 0;
void *new, *new_md;
 
+   /* Keep all regions for /sys/kernel/debug/efi */
+   if (efi_enabled(EFI_DBG))
+   return;
+
for_each_efi_memory_desc(md) {
unsigned long long start = md->phys_addr;
unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index cd42f66a7c85..10c896e8b82b 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -316,6 +317,55 @@ static __init int efivar_ssdt_load(void)
 static inline int efivar_ssdt_load(void) { return 0; }
 #endif
 
+#ifdef CONFIG_DEBUG_FS
+
+#define EFI_DEBUGFS_MAX_BLOBS 32
+
+static struct debugfs_blob_wrapper debugfs_blob[EFI_DEBUGFS_MAX_BLOBS];
+
+static void __init efi_debugfs_init(void)
+{
+   struct dentry *efi_debugfs;
+   efi_memory_desc_t *md;
+   char name[32];
+   int type_count[EFI_BOOT_SERVICES_DATA + 1] = {};
+   int i = 0;
+
+   efi_debugfs = debugfs_create_dir("efi", NULL);
+   if (IS_ERR_OR_NULL(efi_debugfs))
+   return;
+
+   for_each_efi_memory_desc(md) {
+   switch (md->type) {
+   case EFI_BOOT_SERVICES_CODE:
+   snprintf(name, sizeof(name), "boot_services_code%d",
+type_count[md->type]++);
+   break;
+   case EFI_BOOT_SERVICES_DATA:
+   snprintf(name, sizeof(name), "boot_services_data%d",
+type_count[md->type]++);
+   break;
+   default:
+   continue;
+   }
+
+   debugfs_blob[i].size = md->num_pages << EFI_PAGE_SHIFT;
+   debugfs_blob[i].data = memremap(md->phys_addr,
+   debugfs_blob[i].size,
+   MEMREMAP_WB);
+   if (!debugfs_blob[i].data)
+   continue;
+
+   debugfs_create_blob(name, 0400, efi_debugfs, _blob[i]);
+   i++;
+   if (i == EFI_DEBUGFS_MAX_BLOBS)
+   break;
+   }
+}
+#else
+static inline void efi_debugfs_init(void) {}
+#endif
+
 /*
  * We register the efi subsystem with the firmware subsystem and the
  * efivars subsystem with the efi subsystem, if the system was booted with
@@ -360,6 +410,9 @@ static int __init efisubsys_init(void)
goto err_remove_group;
}
 
+   if (efi_enabled(EFI_DBG))
+   efi_debugfs_init();
+
return 0;
 
 err_remove_group:
-- 
2.17.0

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/5] efi: Add embedded peripheral firmware support

2018-04-08 Thread Hans de Goede
Just like with PCI options ROMs, which we save in the setup_efi_pci*
functions from arch/x86/boot/compressed/eboot.c, the EFI code / ROM itself
sometimes may contain data which is useful/necessary for peripheral drivers
to have access to.

Specifically the EFI code may contain an embedded copy of firmware which
needs to be (re)loaded into the peripheral. Normally such firmware would be
part of linux-firmware, but in some cases this is not feasible, for 2
reasons:

1) The firmware is customized for a specific use-case of the chipset / use
with a specific hardware model, so we cannot have a single firmware file
for the chipset. E.g. touchscreen controller firmwares are compiled
specifically for the hardware model they are used with, as they are
calibrated for a specific model digitizer.

2) Despite repeated attempts we have failed to get permission to
redistribute the firmware. This is especially a problem with customized
firmwares, these get created by the chip vendor for a specific ODM and the
copyright may partially belong with the ODM, so the chip vendor cannot
give a blanket permission to distribute these.

This commit adds support for finding peripheral firmware embedded in the
EFI code and making this available to peripheral drivers through the
standard firmware loading mechanism.

Note we check the EFI_BOOT_SERVICES_CODE for embedded firmware near the end
of start_kernel(), just before calling rest_init(), this is on purpose
because the typical EFI_BOOT_SERVICES_CODE memory-segment is too large for
early_memremap(), so the check must be done after mm_init(). This relies
on EFI_BOOT_SERVICES_CODE not being free-ed until efi_free_boot_services()
is called, which means that this will only work on x86 for now.

Reported-by: Dave Olsthoorn <d...@bewaar.me>
Suggested-by: Peter Jones <pjo...@redhat.com>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
Changes in v2:
-Rebased on driver-core/driver-core-next
-Add documentation describing the EFI embedded firmware mechanism to:
 Documentation/driver-api/firmware/request_firmware.rst
-Add a new EFI_EMBEDDED_FIRMWARE Kconfig bool and only build the embedded
 fw support if this is set. This is an invisible option which should be
 selected by drivers which need this
-Remove the efi_embedded_fw_desc and dmi_system_id-s for known devices
 from the efi-embedded-fw code, instead drivers using this are expected to
 export a dmi_system_id array, with each entries' driver_data pointing to a
 efi_embedded_fw_desc struct and register this with the efi-embedded-fw code
-Use kmemdup to make a copy instead of efi_mem_reserve()-ing the firmware,
 this avoids us messing with the EFI memmap and avoids the need to make
 changes to efi_mem_desc_lookup()
-Make the firmware-loader code only fallback to efi_get_embedded_fw() if
 the passed in device has the "efi-embedded-fw" device-property bool set
-Skip usermodehelper fallback when "efi-embedded-firmware" device-property
 is set
---
 .../driver-api/firmware/request_firmware.rst  |  70 +
 drivers/base/firmware_loader/main.c   |  33 
 drivers/firmware/efi/Kconfig  |   6 +
 drivers/firmware/efi/Makefile |   1 +
 drivers/firmware/efi/embedded-firmware.c  | 148 ++
 include/linux/efi.h   |   6 +
 include/linux/efi_embedded_fw.h   |  25 +++
 init/main.c   |   1 +
 8 files changed, 290 insertions(+)
 create mode 100644 drivers/firmware/efi/embedded-firmware.c
 create mode 100644 include/linux/efi_embedded_fw.h

diff --git a/Documentation/driver-api/firmware/request_firmware.rst 
b/Documentation/driver-api/firmware/request_firmware.rst
index 20f21ed427a5..246d52211db7 100644
--- a/Documentation/driver-api/firmware/request_firmware.rst
+++ b/Documentation/driver-api/firmware/request_firmware.rst
@@ -68,3 +68,73 @@ If something went wrong request_firmware() returns non-zero 
and fw_entry
 is set to NULL. Once your driver is done with processing the firmware it
 can call call release_firmware(fw_entry) to release the firmware image
 and any related resource.
+
+EFI embedded firmware support
+=
+
+On some devices the system's EFI code / ROM may contain an embedded copy
+of firmware for some of the system's integrated peripheral devices and
+the peripheral's Linux device-driver needs to access this firmware.
+
+A device driver which needs this can describe the firmware it needs
+using an efi_embedded_fw_desc struct:
+
+.. kernel-doc:: include/linux/efi_embedded_fw.h
+   :functions: efi_embedded_fw_desc
+
+The EFI embedded-fw code works by scanning all EFI_BOOT_SERVICES_CODE memory
+segments for an eight byte sequence matching prefix, if the prefix is found it
+then does a crc32 over length bytes and if that matches makes a copy of length
+bytes and adds that to its list with found firmwares.
+
+To avoid doing this somewhat expen

[PATCH v2 3/5] platform/x86: Rename silead_dmi to touchscreen_dmi

2018-04-08 Thread Hans de Goede
Not only silead touchscreens need some extra info not available in the
ACPI tables to work properly. X86 devices with a Chipone ICN8505 chip also
need some DMI based extra configuration.

There is no reason to have separate dmi config code per touchscreen
controller vendor. This commit renames silead_dmi to a more generic
touchscreen_dmi name (and Kconfig option) in preparation of adding
info for tablets with an ICN8505 based touchscreen.

Note there are no functional changes all code changes are limited to
removing references to silead where these are no longer applicable.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 MAINTAINERS   |  2 +-
 drivers/platform/x86/Kconfig  | 16 ++---
 drivers/platform/x86/Makefile |  2 +-
 .../x86/{silead_dmi.c => touchscreen_dmi.c}   | 66 +--
 4 files changed, 43 insertions(+), 43 deletions(-)
 rename drivers/platform/x86/{silead_dmi.c => touchscreen_dmi.c} (87%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 0d5c55daeeba..99dd47e3b0dd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12618,7 +12618,7 @@ L:  linux-in...@vger.kernel.org
 L: platform-driver-...@vger.kernel.org
 S: Maintained
 F: drivers/input/touchscreen/silead.c
-F: drivers/platform/x86/silead_dmi.c
+F: drivers/platform/x86/touchscreen_dmi.c
 
 SILICON MOTION SM712 FRAME BUFFER DRIVER
 M: Sudip Mukherjee <sudipm.mukher...@gmail.com>
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 1868aab0282a..b836576f0fe4 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1194,16 +1194,16 @@ config INTEL_TURBO_MAX_3
  This driver is only required when the system is not using Hardware
  P-States (HWP). In HWP mode, priority can be read from ACPI tables.
 
-config SILEAD_DMI
-   bool "Tablets with Silead touchscreens"
+config TOUCHSCREEN_DMI
+   bool "DMI based touchscreen configuration info"
depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD
---help---
- Certain ACPI based tablets with Silead touchscreens do not have
- enough data in ACPI tables for the touchscreen driver to handle
- the touchscreen properly, as OEMs expected the data to be baked
- into the tablet model specific version of the driver shipped
- with the OS-image for the device. This option supplies the missing
- information. Enable this for x86 tablets with Silead touchscreens.
+ Certain ACPI based tablets with e.g. Silead or Chipone touchscreens
+ do not have enough data in ACPI tables for the touchscreen driver to
+ handle the touchscreen properly, as OEMs expect the data to be baked
+ into the tablet model specific version of the driver shipped with the
+ the OS-image for the device. This option supplies the missing info.
+ Enable this for x86 tablets with Silead or Chipone touchscreens.
 
 config INTEL_CHTDC_TI_PWRBTN
tristate "Intel Cherry Trail Dollar Cove TI power button driver"
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 2ba6cb795338..8d9477114fb5 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -78,7 +78,7 @@ obj-$(CONFIG_INTEL_SMARTCONNECT)  += intel-smartconnect.o
 obj-$(CONFIG_PVPANIC)   += pvpanic.o
 obj-$(CONFIG_ALIENWARE_WMI)+= alienware-wmi.o
 obj-$(CONFIG_INTEL_PMC_IPC)+= intel_pmc_ipc.o
-obj-$(CONFIG_SILEAD_DMI)   += silead_dmi.o
+obj-$(CONFIG_TOUCHSCREEN_DMI)  += touchscreen_dmi.o
 obj-$(CONFIG_SURFACE_PRO3_BUTTON)  += surfacepro3_button.o
 obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o
 obj-$(CONFIG_INTEL_PUNIT_IPC)  += intel_punit_ipc.o
diff --git a/drivers/platform/x86/silead_dmi.c 
b/drivers/platform/x86/touchscreen_dmi.c
similarity index 87%
rename from drivers/platform/x86/silead_dmi.c
rename to drivers/platform/x86/touchscreen_dmi.c
index 452aacabaa8e..87fc839b28f7 100644
--- a/drivers/platform/x86/silead_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -1,5 +1,5 @@
 /*
- * Silead touchscreen driver DMI based configuration code
+ * Touchscreen driver DMI based configuration code
  *
  * Copyright (c) 2017 Red Hat Inc.
  *
@@ -20,7 +20,7 @@
 #include 
 #include 
 
-struct silead_ts_dmi_data {
+struct ts_dmi_data {
const char *acpi_name;
const struct property_entry *properties;
 };
@@ -34,7 +34,7 @@ static const struct property_entry cube_iwork8_air_props[] = {
{ }
 };
 
-static const struct silead_ts_dmi_data cube_iwork8_air_data = {
+static const struct ts_dmi_data cube_iwork8_air_data = {
.acpi_name  = "MSSL1680:00",
.properties = cube_iwork8_air_props,
 };
@@ -48,7 +48,7 @@ static const struct property_entry jumper_ezpad_mini3_props[] 
= {
{ }
 };
 
-static const stru

[PATCH v2 5/5] platform/x86: touchscreen_dmi: Add info for the Chuwi Vi8 Plus tablet

2018-04-08 Thread Hans de Goede
Add touchscreen info for the Chuwi Vi8 Plus tablet. This tablet uses a
Chipone ICN8505 touchscreen controller, with the firmware used by the
touchscreen embedded in the EFI firmware.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 drivers/platform/x86/touchscreen_dmi.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/drivers/platform/x86/touchscreen_dmi.c 
b/drivers/platform/x86/touchscreen_dmi.c
index 6488cd50ba79..5fdb6fe878f4 100644
--- a/drivers/platform/x86/touchscreen_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -301,6 +301,22 @@ static const struct ts_dmi_data teclast_x3_plus_data = {
.properties = teclast_x3_plus_props,
 };
 
+static const struct property_entry efi_embedded_fw_props[] = {
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
+   { }
+};
+
+static const struct ts_dmi_data chuwi_vi8_plus_data = {
+   .embedded_fw = {
+   .name   = "chipone/icn8505-HAMP0002.fw",
+   .prefix = { 0xb0, 0x07, 0x00, 0x00, 0xe4, 0x07, 0x00, 0x00 },
+   .length = 35012,
+   .crc= 0x74dfd3fc,
+   },
+   .acpi_name  = "CHPN0001:00",
+   .properties = efi_embedded_fw_props,
+};
+
 const struct dmi_system_id touchscreen_dmi_table[] = {
{
/* CUBE iwork8 Air */
@@ -487,6 +503,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"),
},
},
+   {
+   /* Chuwi Vi8 Plus (CWI506) */
+   .driver_data = (void *)_vi8_plus_data,
+   .matches = {
+   DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
+   DMI_MATCH(DMI_PRODUCT_NAME, "D2D3_Vi8A1"),
+   DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+   },
+   },
{ },
 };
 
-- 
2.17.0

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 4/5] platform/x86: touchscreen_dmi: Add EFI embedded firmware info support

2018-04-08 Thread Hans de Goede
Sofar we have been unable to get permission from the vendors to put the
firmware for touchscreens listed in touchscreen_dmi in linux-firmware.

Some of the tablets with such a touchscreen have a touchscreen driver, and
thus a copy of the firmware, as part of their EFI code.

This commit adds the necessary info for the new EFI embedded-firmware code
to extract these firmwares, making the touchscreen work OOTB without the
user needing to manually add the firmware.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 drivers/firmware/efi/embedded-firmware.c |  3 +++
 drivers/platform/x86/Kconfig |  1 +
 drivers/platform/x86/touchscreen_dmi.c   | 26 +++-
 include/linux/efi_embedded_fw.h  |  2 ++
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/embedded-firmware.c 
b/drivers/firmware/efi/embedded-firmware.c
index cb57225a340d..26101ac1a282 100644
--- a/drivers/firmware/efi/embedded-firmware.c
+++ b/drivers/firmware/efi/embedded-firmware.c
@@ -23,6 +23,9 @@ struct embedded_fw {
 static LIST_HEAD(found_fw_list);
 
 static const struct dmi_system_id * const embedded_fw_table[] = {
+#ifdef CONFIG_TOUCHSCREEN_DMI
+   touchscreen_dmi_table,
+#endif
NULL
 };
 
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index b836576f0fe4..5bb0f5edd7f2 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1197,6 +1197,7 @@ config INTEL_TURBO_MAX_3
 config TOUCHSCREEN_DMI
bool "DMI based touchscreen configuration info"
depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD
+   select EFI_EMBEDDED_FIRMWARE if EFI_STUB
---help---
  Certain ACPI based tablets with e.g. Silead or Chipone touchscreens
  do not have enough data in ACPI tables for the touchscreen driver to
diff --git a/drivers/platform/x86/touchscreen_dmi.c 
b/drivers/platform/x86/touchscreen_dmi.c
index 87fc839b28f7..6488cd50ba79 100644
--- a/drivers/platform/x86/touchscreen_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -15,12 +15,15 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 
 struct ts_dmi_data {
+   /* The EFI embedded-fw code expects this to be the first member! */
+   struct efi_embedded_fw_desc embedded_fw;
const char *acpi_name;
const struct property_entry *properties;
 };
@@ -31,10 +34,17 @@ static const struct property_entry cube_iwork8_air_props[] 
= {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
{ }
 };
 
 static const struct ts_dmi_data cube_iwork8_air_data = {
+   .embedded_fw = {
+   .name   = "silead/gsl3670-cube-iwork8-air.fw",
+   .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+   .length = 38808,
+   .crc= 0xfecde51f,
+   },
.acpi_name  = "MSSL1680:00",
.properties = cube_iwork8_air_props,
 };
@@ -119,10 +129,17 @@ static const struct property_entry pipo_w2s_props[] = {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name",
  "gsl1680-pipo-w2s.fw"),
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
{ }
 };
 
 static const struct ts_dmi_data pipo_w2s_data = {
+   .embedded_fw = {
+   .name   = "silead/gsl1680-pipo-w2s.fw",
+   .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+   .length = 39072,
+   .crc= 0x28d5dc6c,
+   },
.acpi_name  = "MSSL1680:00",
.properties = pipo_w2s_props,
 };
@@ -162,10 +179,17 @@ static const struct property_entry chuwi_hi8_pro_props[] 
= {
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"),
PROPERTY_ENTRY_BOOL("silead,home-button"),
+   PROPERTY_ENTRY_BOOL("efi-embedded-firmware"),
{ }
 };
 
 static const struct ts_dmi_data chuwi_hi8_pro_data = {
+   .embedded_fw = {
+   .name   = "silead/gsl3680-chuwi-hi8-pro.fw",
+   .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+   .length = 39864,
+   .crc= 0xfe2bedba,
+   },
.acpi_name  = "MSSL1680:00",
.properties = chuwi_hi8_pro_props,
 };
@@ -277,7 +301,7 @@ static const struct ts_dmi_data teclast_x3_plus_data = {
.properties = teclast_x3_plus_props,
 };
 
-static const struct dmi_system_id tou

Re: [PATCH 2/2] efi: Add embedded peripheral firmware support

2018-04-07 Thread Hans de Goede

Hi,

On 06-04-18 16:08, Luis R. Rodriguez wrote:

On Thu, Apr 05, 2018 at 07:43:49AM +0200, Lukas Wunner wrote:

On Wed, Apr 04, 2018 at 01:18:36PM -0400, Peter Jones wrote:

On Tue, Apr 03, 2018 at 08:07:11PM +0200, Lukas Wunner wrote:

* Add the EFI Firmware Volume Protocol to include/linux/efi.h:
   
https://www.intel.com/content/dam/doc/reference-guide/efi-firmware-file-volume-specification.pdf

* Amend arch/x86/boot/compressed/eboot.c to read the files with the
   GUIDs you're interested in into memory and pass the files to the
   kernel as setup_data payloads.


To be honest, I'm a bit skeptical about the firmware volume approach.
Tools like UEFITool[0] and uefi-firmware-parser[1] have existed for
years, still don't seem to reliably parse firmware images I see in the
wild, and have a fairly regular need for fixes.  These are tools
maintained by smart people who are making a real effort, and it still
looks pretty hard to do a good job that applies across a lot of
platforms.

So I'd rather use Hans's existing patches, at least for now, and if
someone is interested in hacking on making an efi firmware volume parser
for the kernel, switch them to that when such a thing is ready.


Hello?  As I've written in the above-quoted e-mail the kernel should
read the files using EFI_FIRMWARE_VOLUME_PROTOCOL.ReadFile().

*Not* by parsing the firmware volume!

Parsing the firmware volume is only necessary to find out the GUIDs
of the files you're looking for.  You only do that *once*.


How do you get the GUIDs for each driver BTW?

Hans, I do believe we should *try* this approach at the very least.


Ok, so I've made a ROM dump of one of the tablets which I have with
the touchscreen firmware embedded in the EFI code using flashrom,
then I ran UEFIExtract on it, to get all the separate files.

Then I wrote a little test.sh script using hexdump piped to grep to
find the magic prefix, here is the result of running this on all
files UEFIExtract generated:

[hans@shalem chuwi-vi8-plus-cwi519-bios.bin.dump]$ find -type f -exec ./test.sh 
'{}' \;
0x0c403136B0 07 00 00 E4 07 00 00
found in ./2 BIOS region/6 8C8CE578-8A3D-4F1C-9935-896185C32DD3/31 I2cHid/1 
EE4E5898-3914-4259-9D6E-DC7BD79403CF/0 PE32 image section/body.bin
0x0be03040B0 07 00 00 E4 07 00 00
found in ./2 BIOS region/5 8C8CE578-8A3D-4F1C-9935-896185C32DD3/31 I2cHid/1 
EE4E5898-3914-4259-9D6E-DC7BD79403CF/0 PE32 image section/body.bin

With the version found at offset 0xbe0 of the "5 
8C8CE578-8A3D-4F1C-9935-896185C32DD3"
section matching what we find in the efi_boot_services_code while running.

As the I2cHid name suggests this is embedded in the driver (which is a PE 
executable), not in a separate file:
[hans@shalem chuwi-vi8-plus-cwi519-bios.bin.dump]$ file './2 BIOS region/5 
8C8CE578-8A3D-4F1C-9935-896185C32DD3/31 I2cHid/1 
EE4E5898-3914-4259-9D6E-DC7BD79403CF/0 PE32 image section/body.bin'
./2 BIOS region/5 8C8CE578-8A3D-4F1C-9935-896185C32DD3/31 I2cHid/1 
EE4E5898-3914-4259-9D6E-DC7BD79403CF/0 PE32 image section/body.bin: MS-DOS 
executable

So using the EFI_FIRMWARE_VOLUME_PROTOCOL.ReadFile() is not really
going to help here, since this is not in a separate file which we
can consume in its entirety, we still need to scan for the prefix
and do e.g. a CRC check to make sure we've actually got what we
expect, at which point simply scanning all of efi_boot_services_code
is a lot simpler and less error prone.

Using an implementation specific EFI protocol for this means calling
into EFI code and potentially triggering various bugs in there, breaking
boot. This is esp. likely to happen since this is a protocol which is
not used outside of the EFI ROMs internal code so there are likely
little ABI guarantees making this approach extra error prone.

Just scanning the efi_boot_services_code OTOH is quite safe TODO.

As for the overhead of scanning the efi_boot_services_code, we are
only doing this on a dmi match, so on most machines there is no
overhead other then the dmi check. On machines where there is
a dmi match, the price (I guess about 30 ms or so for the scan)
is well worth the result of having the touchscreen OOTB.

Regard,

Hans



--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] efi: Add embedded peripheral firmware support

2018-04-05 Thread Hans de Goede

Hi,

On 03-04-18 20:47, Luis R. Rodriguez wrote:

In your next patches please Cc the folks I added for future review as well.
We don't have a mailing list for the firmware API so I just tend to Cc
who I think should help review when needed.


Hmm, quite a long Cc list, but ok.


On Tue, Apr 03, 2018 at 10:33:25AM +0200, Hans de Goede wrote:





This is not part of the standard. There has been a long(ish) standing issue
with us not being able to get re-distribute permission for the firmware for
some touchscreen controllers found on cheap x86 devices. Which means that
we cannot put it in Linux firmware.


BTW do these cheap x86 devices have hw signing support?


Not sure what you mean with hw signing support here, they support UEFI
secure-boot and have a fTPM.


Just curious thinking
long term here. Because of it is not-standard then perhaps wen can partner
later up with a vendor to this properly and actually support hw firmware
singing.


Dave Olsthoorn (in the Cc) noticed that the touchscreen did work in the
refind bootload UI, so the EFI code must have a copy of the firmware.


:)


I asked Peter Jones for suggestions how to extract this during boot and
he suggested seeing if there was a copy of the firmware in the
EFI_BOOT_SERVICES_CODE memory segment, which it turns out there is.


Sneaky Pete, nice. So essentially we're reverse engineering support for this.


Yes.


Anyway please mention that this is not part of standard in the documentation,
and we've just found out in practice some vendors are doing this. That would
avoid having people ask later.


Ok, I will add some docs for v2 of the patch.


My patch to add support for this contains a table of device-model (dmi
strings), firmware header (first 64 bits), length and crc32 and then if
we boot on a device-model which is in the table the code scans the
EFI_BOOT_SERVICES_CODE for the prefix, if found checks the crc and
caches the firmware for later use by request-firmware.


Neat, best to add proper docs for this.


Ok.


So I just do a brute-force search for the firmware, this really is hack,
nothing standard about it I'm afraid. But it works on 4 different x86
tablets I have and makes the touchscreen work OOTB on them, so I believe
it is a worthwhile hack to have.


Absolutely, just not to shove an entire fallback firmware path to all users.


Ok.




What mechanism would have in place to ensure that a driver which expects
firmware to be on EFI data to be already available prior to its driver's
call to initialize?


See above, this still runs before start_kernel() calls rest_init() which is
where any normal init calls (and driver probing) happens so still early
enough for any users I can think of.


The firmware API is even used to load microcode, but that relies on built-in
firmware support. That code needs to be refactored to be a proper citizen of the
firmware API, right now its just a hack. Reason for asking all these details
was to ensure we document the restrictions correctly so that expecations are
set correctly for callers prior to rest_init(). Please be sure to document the
limitations.


Ok.




This means we rely on the EFI_BOOT_SERVICES_CODE not being free-ed until
efi_free_boot_services() is called, which means that this will only work
on x86, if we ever want this on ARM we should make ARM delay the freeing
of the EFI_BOOT_SERVICES_* memory-segments too.


Why not do that as well with your patch?


That requires making significant changes to the early bringup code on
ARM, x86 keeps EFI_BOOT_SERVICES_* memory-segments around until near
the end of start_kernel() because freeing them earlier triggers bugs
in some x86 EFI implementations, ARM EFI implementations do not have
these bugs, so they free them almost directly at boot.

Changing this really falls outside the scope of this patch.


Sure but did you poke ARM folks about it? Maybe they can do it?
And if this becomes a common practice, perhaps they can do it with
actual firmware signing instead of a CRC.

Not sure how hard it is to exploit EFI_BOOT_SERVICES_CODE... but it
may help UEFI folks with a nice warm fuzzy to start doing this right
later instead of propagating what seems to be a cheap hack.


If things are compromised before the kernel boots no amount of
checks are going to help us, an attacker can then just boot an entirely
different kernel, rather then attacking the system through a backdoored
firmware, so a CRC should be fine. Either way I'm happy to switch to a
crypto hash, but the crypto subsystem is not initialized yet at this
point AFAICT, so using a CRC is easier.


Note this commit also modifies efi_mem_desc_lookup() to not skip
EFI_BOOT_SERVICES_CODE memory-segments, so that efi_mem_reserve() works
on such segments.

Reported-by: Dave Olsthoorn <d...@bewaar.me>
Suggested-by: Peter Jones <pjo...@redhat.com>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
   drivers/base/firmware_class.c|  29 +++
   drivers/firmware/efi/Makefil

Re: [PATCH 2/2] efi: Add embedded peripheral firmware support

2018-04-05 Thread Hans de Goede

Hi,

On 03-04-18 21:53, Peter Jones wrote:

On Sat, Mar 31, 2018 at 02:19:44PM +0200, Hans de Goede wrote:

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index fddc5f706fd2..1a5ea950f58f 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -455,6 +455,7 @@ int __init efi_mem_desc_lookup(u64 phys_addr, 
efi_memory_desc_t *out_md)
u64 end;
  
  		if (!(md->attribute & EFI_MEMORY_RUNTIME) &&

+   md->type != EFI_BOOT_SERVICES_CODE &&
md->type != EFI_BOOT_SERVICES_DATA &&
md->type != EFI_RUNTIME_SERVICES_DATA) {
continue;


Might be worth adding a comment here to ensure nobody comes along later
and adds something like EFI_BOOT_LOADER_DATA or other stuff that's
allocated later here.  I don't want to accidentally patch our way into
having the ability to stumble across a firmware blob somebody dumped
into the middle of a grub config file, especially since you only need to
collide crc32 (within the same length) to pre-alias a match.


As discussed elsewhere in the thread, I'm going to switch to doing a
kmemdup on the found firmware, so this chunk will go away :)



...

+static int __init efi_check_md_for_embedded_firmware(
+   efi_memory_desc_t *md, const struct embedded_fw_desc *desc)
+{

...

+   if (found_fw_count >= MAX_EMBEDDED_FIRMWARES) {
+   pr_err("Error already have %d embedded firmwares\n",
+  MAX_EMBEDDED_FIRMWARES);
+   return -ENOSPC;
+   }


Doesn't seem like this needs to be pr_err(); after all we have already
found a valid match, so the firmware vendor has done something
moderately stupid, but we have a firmware that will probably work.  Of
course it still needs to return != 0, but pr_warn() or even pr_info()
seems more reasonable.


We break from the search loop as soon as a firmware is found, this can
only trigger if someone adds a second firmware to the dmi data and then
does not update MAX_EMBEDDED_FIRMWARES...

But mcgrof wants me to switch to a linked list here, so this is going
away too.


Aside from those nits, looks good to me.

Reviewed-by: Peter Jones <pjo...@redhat.com>


Thanks, but v2 is going to have so much changes that I don't feel
comfortable bringing this forward to v2.

Regards,

Hans

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] efi: Add embedded peripheral firmware support

2018-04-04 Thread Hans de Goede

HI,

On 04-04-18 19:18, Peter Jones wrote:

On Tue, Apr 03, 2018 at 06:58:48PM +, Luis R. Rodriguez wrote:

On Tue, Apr 03, 2018 at 08:07:11PM +0200, Lukas Wunner wrote:

On Tue, Apr 03, 2018 at 10:33:25AM +0200, Hans de Goede wrote:

I asked Peter Jones for suggestions how to extract this during boot and
he suggested seeing if there was a copy of the firmware in the
EFI_BOOT_SERVICES_CODE memory segment, which it turns out there is.

My patch to add support for this contains a table of device-model (dmi
strings), firmware header (first 64 bits), length and crc32 and then if
we boot on a device-model which is in the table the code scans the
EFI_BOOT_SERVICES_CODE for the prefix, if found checks the crc and
caches the firmware for later use by request-firmware.

So I just do a brute-force search for the firmware, this really is hack,
nothing standard about it I'm afraid. But it works on 4 different x86
tablets I have and makes the touchscreen work OOTB on them, so I believe
it is a worthwhile hack to have.


The EFI Firmware Volume contains a kind of filesystem with files
identified by GUIDs.  Those files include EFI drivers, ACPI tables,
DMI data and so on.  It is actually quite common for vendors to
also include device firmware on the Firmware Volume.  Apple is doing
this to ship firmware updates e.g. for the GMUX controller found on
dual GPU MacBook Pros.  If they want to update the controller's
firmware, they include it in a BIOS update, and an EFI driver checks
on boot if the firmware update for the controller is necessary and
if so, flashes it.

The firmware files you're looking for are almost certainly included
on the Firmware Volume as individual files.


What Hans implemented seems to have been for a specific x86 hack, best if we
confirm if indeed they are present on the Firmware Volume.


To be honest, I'm a bit skeptical about the firmware volume approach.
Tools like UEFITool[0] and uefi-firmware-parser[1] have existed for
years, still don't seem to reliably parse firmware images I see in the
wild, and have a fairly regular need for fixes.  These are tools
maintained by smart people who are making a real effort, and it still
looks pretty hard to do a good job that applies across a lot of
platforms.

So I'd rather use Hans's existing patches, at least for now, and if
someone is interested in hacking on making an efi firmware volume parser
for the kernel, switch them to that when such a thing is ready.

[0] g...@github.com:LongSoft/UEFITool.git
[1] g...@github.com:theopolis/uefi-firmware-parser.git


Rather than scraping
the EFI memory for firmware, I think it would be cleaner and more
elegant if you just retrieve the files you're interested in from
the Firmware Volume.

We're doing something similar with Apple EFI properties, see
58c5475aba67 and c9cc3aaa0281.

Basically what you need to do to implement this approach is:

* Determine the GUIDs used by vendors for the files you're interested
   in.  Either dump the Firmware Volume or take an EFI update as
   shipped by the vendor, then feed it to UEFIExtract:
   https://github.com/LongSoft/UEFITool
   
* Add the EFI Firmware Volume Protocol to include/linux/efi.h:

   
https://www.intel.com/content/dam/doc/reference-guide/efi-firmware-file-volume-specification.pdf

* Amend arch/x86/boot/compressed/eboot.c to read the files with the
   GUIDs you're interested in into memory and pass the files to the
   kernel as setup_data payloads.

* Once the kernel has booted, make the files you've retrieved
   available to device drivers as firmware blobs.


Happen to know if devices using Firmware Volumes also sign their firmware
and if hw checks the firmware at load time?


It varies on a per-device basis, of course.  Most new Intel machines as
of Haswell *should* be verifying their system firmware via Boot Guard,
which both checks an RSA signature and measures the firmware into the
TPM, but as with everything of this nature, there are certainly vendors
that screw it up. (I think AMD has something similar, but I'm really not
sure.)


Lukas, thank you for your suggestions on this, but I doubt that these
devices use the Firmware Volume stuff.

These are really cheap x86 Windows 10 tablets, everything about them is
simply hacked together by the manufacturer till it boots Windows10 and
then it is shipped to the customer without receiving any update
afterwards ever.

What you are describing sounds like significantly more work then
the vendor just embedding the firmware as a char firmware[] in their
EFI mouse driver.

That combined with Peter's worries about difficulties parsing the
Firmware Volume stuff, makes me believe that it is best to just
stick with my current approach as Peter suggests.

Regards,

Hans

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] efi: Add embedded peripheral firmware support

2018-04-03 Thread Hans de Goede

Hi Luis,

Thank you for the review.

On 03-04-18 01:23, Luis R. Rodriguez wrote:

On Sat, Mar 31, 2018 at 02:19:44PM +0200, Hans de Goede wrote:

Just like with PCI options ROMs, which we save in the setup_efi_pci*
functions from arch/x86/boot/compressed/eboot.c, the EFI code / ROM itself
sometimes may contain data which is useful/necessary for peripheral drivers
to have access to.

Specifically the EFI code may contain an embedded copy of firmware which
needs to be (re)loaded into the peripheral. Normally such firmware would be
part of linux-firmware, but in some cases this is not feasible, for 2
reasons:

1) The firmware is customized for a specific use-case of the chipset / use
with a specific hardware model, so we cannot have a single firmware file
for the chipset. E.g. touchscreen controller firmwares are compiled
specifically for the hardware model they are used with, as they are
calibrated for a specific model digitizer.


Some devices have OTP and use this sort of calibration data,


Right, I'm not sure it really is OTP and not flash, but many touchscreen
controllers do come with their firmware embedded into the controller, but
not all unfortunately.


I was unaware of
the use of EFI to stash firmware. Good to know, but can you also provide
references to what part of what standard should be followed for it in
documentation?


This is not part of the standard. There has been a long(ish) standing issue
with us not being able to get re-distribute permission for the firmware for
some touchscreen controllers found on cheap x86 devices. Which means that
we cannot put it in Linux firmware.

Dave Olsthoorn (in the Cc) noticed that the touchscreen did work in the
refind bootload UI, so the EFI code must have a copy of the firmware.

I asked Peter Jones for suggestions how to extract this during boot and
he suggested seeing if there was a copy of the firmware in the
EFI_BOOT_SERVICES_CODE memory segment, which it turns out there is.

My patch to add support for this contains a table of device-model (dmi
strings), firmware header (first 64 bits), length and crc32 and then if
we boot on a device-model which is in the table the code scans the
EFI_BOOT_SERVICES_CODE for the prefix, if found checks the crc and
caches the firmware for later use by request-firmware.

So I just do a brute-force search for the firmware, this really is hack,
nothing standard about it I'm afraid. But it works on 4 different x86
tablets I have and makes the touchscreen work OOTB on them, so I believe
it is a worthwhile hack to have.


2) Despite repeated attempts we have failed to get permission to
redistribute the firmware. This is especially a problem with customized
firmwares, these get created by the chip vendor for a specific ODM and the
copyright may partially belong with the ODM, so the chip vendor cannot
give a blanket permission to distribute these.

This commit adds support for finding peripheral firmware embedded in the
EFI code and making this available to peripheral drivers through the
standard firmware loading mechanism.


Neat.


Note we check the EFI_BOOT_SERVICES_CODE for embedded firmware pretty
late in the init sequence,


This also creates a technical limitation on use for the API that users
should be aware of. Its important to document such limitation.


I don't think this is a problem for any normal drivers, when I say pretty
late I mean late in init/main.c: start_kernel(), so still before any normal
drivers load.

The first idea was to scan for the firmware at the same time we check for
things as the ACPI BGRT logo stuff, but as mentioned that requires using
early_mmap() which does not work for the amount of memory we want to map.


Also if we can address the limitation that would be even better.

For instance, on what part of the driver is the call to request firmware
being made? Note that we support async probe now, so if the call was done
on probe, it may be wise to use async probe, however, can we be *certain*
that the EFI firmware would have been parsed and ready by then? Please
check. It just may be the case.

Or, if we use late_initcall() would that suffice on the driver, if they
used a request firmware call on init or probe?


As said I think we still do it early enough for any driver use, when
I wrote "late in the init sequence" I should have probably written something
else, like "near the end of start_kernel() instead of from setup_arch()"




this is on purpose because the typical
EFI_BOOT_SERVICES_CODE memory-segment is too large for early_memremap().


To be clear you neede to use memremap()


Yes.


What mechanism would have in place to ensure that a driver which expects
firmware to be on EFI data to be already available prior to its driver's
call to initialize?


See above, this still runs before start_kernel() calls rest_init() which is
where any normal init calls (and driver probing) happens so still early
enough for any users I can think of. I think my poorly worded commi

Re: [PATCH 1/2] efi: Export boot-services code and data as debugfs-blobs

2018-03-31 Thread Hans de Goede

Hi,

On 03/31/2018 04:10 PM, Greg Kroah-Hartman wrote:

On Sat, Mar 31, 2018 at 02:19:43PM +0200, Hans de Goede wrote:

Sometimes it is useful to be able to dump the efi boot-services code and
data. This commit adds these as debugfs-blobs to /sys/kernel/debug/efi,
but only if efi=debug is passed on the kernel-commandline as this requires
not freeing those memory-regions, which costs 20+ MB of RAM.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
  arch/x86/platform/efi/quirks.c |  4 +++
  drivers/firmware/efi/efi.c | 57 ++
  2 files changed, 61 insertions(+)

diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 5b513ccffde4..0f968c7bcfec 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -374,6 +374,10 @@ void __init efi_free_boot_services(void)
int num_entries = 0;
void *new, *new_md;
  
+	/* Keep all regions for /sys/kernel/debug/efi */

+   if (efi_enabled(EFI_DBG))
+   return;
+
for_each_efi_memory_desc(md) {
unsigned long long start = md->phys_addr;
unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index cd42f66a7c85..fddc5f706fd2 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -18,6 +18,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -316,6 +317,59 @@ static __init int efivar_ssdt_load(void)
  static inline int efivar_ssdt_load(void) { return 0; }
  #endif
  
+#ifdef CONFIG_DEBUG_FS

+
+#define EFI_DEBUGFS_MAX_BLOBS 32
+
+struct debugfs_blob_wrapper debugfs_blob[EFI_DEBUGFS_MAX_BLOBS];
+
+static void __init efi_debugfs_init(void)
+{
+   struct dentry *efi_debugfs;
+   efi_memory_desc_t *md;
+   char name[32];
+   int type_count[EFI_BOOT_SERVICES_DATA + 1] = {};
+   int i = 0;
+
+   efi_debugfs = debugfs_create_dir("efi", NULL);
+   if (IS_ERR_OR_NULL(efi_debugfs)) {
+   pr_warn("Could not create efi debugfs entry\n");
+   return;
+   }


{sigh}

No, don't warn, or complain, or do anything else if a debugfs call
fails.  Just keep on moving, you can always use the return value
properly in any future call if you need it, and no code flow should ever
care if a debugfs call succeeded or failed.


Ok.


  /*
   * We register the efi subsystem with the firmware subsystem and the
   * efivars subsystem with the efi subsystem, if the system was booted with
@@ -360,6 +414,9 @@ static int __init efisubsys_init(void)
goto err_remove_group;
}
  
+	if (efi_enabled(EFI_DBG))

+   efi_debugfs_init();


You never remove the directory?


Correct, this is happening from a subsys_initcall as such there is no
efi_cleanup() counterpart.

Note the "if (efi_enabled(EFI_DBG))" check checks for efi=debug on the
kernel cmdline, so this only happens if the user asked for it.

Regards,

Hans

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] efi: Add embedded peripheral firmware support

2018-03-31 Thread Hans de Goede
Just like with PCI options ROMs, which we save in the setup_efi_pci*
functions from arch/x86/boot/compressed/eboot.c, the EFI code / ROM itself
sometimes may contain data which is useful/necessary for peripheral drivers
to have access to.

Specifically the EFI code may contain an embedded copy of firmware which
needs to be (re)loaded into the peripheral. Normally such firmware would be
part of linux-firmware, but in some cases this is not feasible, for 2
reasons:

1) The firmware is customized for a specific use-case of the chipset / use
with a specific hardware model, so we cannot have a single firmware file
for the chipset. E.g. touchscreen controller firmwares are compiled
specifically for the hardware model they are used with, as they are
calibrated for a specific model digitizer.

2) Despite repeated attempts we have failed to get permission to
redistribute the firmware. This is especially a problem with customized
firmwares, these get created by the chip vendor for a specific ODM and the
copyright may partially belong with the ODM, so the chip vendor cannot
give a blanket permission to distribute these.

This commit adds support for finding peripheral firmware embedded in the
EFI code and making this available to peripheral drivers through the
standard firmware loading mechanism.

Note we check the EFI_BOOT_SERVICES_CODE for embedded firmware pretty
late in the init sequence, this is on purpose because the typical
EFI_BOOT_SERVICES_CODE memory-segment is too large for early_memremap().
This means we rely on the EFI_BOOT_SERVICES_CODE not being free-ed until
efi_free_boot_services() is called, which means that this will only work
on x86, if we ever want this on ARM we should make ARM delay the freeing
of the EFI_BOOT_SERVICES_* memory-segments too.

Note this commit also modifies efi_mem_desc_lookup() to not skip
EFI_BOOT_SERVICES_CODE memory-segments, so that efi_mem_reserve() works
on such segments.

Reported-by: Dave Olsthoorn <d...@bewaar.me>
Suggested-by: Peter Jones <pjo...@redhat.com>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 drivers/base/firmware_class.c|  29 +++
 drivers/firmware/efi/Makefile|   1 +
 drivers/firmware/efi/efi.c   |   1 +
 drivers/firmware/efi/embedded-firmware.c | 232 +++
 include/linux/efi.h  |   2 +
 init/main.c  |   1 +
 6 files changed, 266 insertions(+)
 create mode 100644 drivers/firmware/efi/embedded-firmware.c

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 7dd36ace6152..b1e7b3de1975 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -12,6 +12,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1207,6 +1208,32 @@ static inline void unregister_sysfs_loader(void)
 
 #endif /* CONFIG_FW_LOADER_USER_HELPER */
 
+#ifdef CONFIG_EFI
+static int
+fw_get_efi_embedded_fw(struct device *dev, struct fw_priv *fw_priv, int ret)
+{
+   size_t size;
+   int rc;
+
+   rc = efi_get_embedded_fw(fw_priv->fw_name, _priv->data, ,
+fw_priv->data ? fw_priv->allocated_size : 0);
+   if (rc == 0) {
+   dev_dbg(dev, "using efi-embedded fw %s\n", fw_priv->fw_name);
+   fw_priv->size = size;
+   fw_state_done(fw_priv);
+   ret = 0;
+   }
+
+   return ret;
+}
+#else
+static inline int
+fw_get_efi_embedded_fw(struct device *dev, struct fw_priv *fw_priv, int ret)
+{
+   return ret;
+}
+#endif
+
 /* prepare firmware and firmware_buf structs;
  * return 0 if a firmware is already assigned, 1 if need to load one,
  * or a negative error code
@@ -1296,6 +1323,8 @@ _request_firmware(const struct firmware **firmware_p, 
const char *name,
goto out;
 
ret = fw_get_filesystem_firmware(device, fw->priv);
+   if (ret)
+   ret = fw_get_efi_embedded_fw(device, fw->priv, ret);
if (ret) {
if (!(opt_flags & FW_OPT_NO_WARN))
dev_warn(device,
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index cb805374f4bc..cb946f7d0181 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -13,6 +13,7 @@ KASAN_SANITIZE_runtime-wrappers.o := n
 obj-$(CONFIG_ACPI_BGRT)+= efi-bgrt.o
 obj-$(CONFIG_EFI)  += efi.o vars.o reboot.o memattr.o tpm.o
 obj-$(CONFIG_EFI)  += capsule.o memmap.o
+obj-$(CONFIG_EFI)  += embedded-firmware.o
 obj-$(CONFIG_EFI_VARS) += efivars.o
 obj-$(CONFIG_EFI_ESRT) += esrt.o
 obj-$(CONFIG_EFI_VARS_PSTORE)  += efi-pstore.o
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index fddc5f706fd2..1a5ea950f58f 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/

[PATCH 1/2] efi: Export boot-services code and data as debugfs-blobs

2018-03-31 Thread Hans de Goede
Sometimes it is useful to be able to dump the efi boot-services code and
data. This commit adds these as debugfs-blobs to /sys/kernel/debug/efi,
but only if efi=debug is passed on the kernel-commandline as this requires
not freeing those memory-regions, which costs 20+ MB of RAM.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 arch/x86/platform/efi/quirks.c |  4 +++
 drivers/firmware/efi/efi.c | 57 ++
 2 files changed, 61 insertions(+)

diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 5b513ccffde4..0f968c7bcfec 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -374,6 +374,10 @@ void __init efi_free_boot_services(void)
int num_entries = 0;
void *new, *new_md;
 
+   /* Keep all regions for /sys/kernel/debug/efi */
+   if (efi_enabled(EFI_DBG))
+   return;
+
for_each_efi_memory_desc(md) {
unsigned long long start = md->phys_addr;
unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index cd42f66a7c85..fddc5f706fd2 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -316,6 +317,59 @@ static __init int efivar_ssdt_load(void)
 static inline int efivar_ssdt_load(void) { return 0; }
 #endif
 
+#ifdef CONFIG_DEBUG_FS
+
+#define EFI_DEBUGFS_MAX_BLOBS 32
+
+struct debugfs_blob_wrapper debugfs_blob[EFI_DEBUGFS_MAX_BLOBS];
+
+static void __init efi_debugfs_init(void)
+{
+   struct dentry *efi_debugfs;
+   efi_memory_desc_t *md;
+   char name[32];
+   int type_count[EFI_BOOT_SERVICES_DATA + 1] = {};
+   int i = 0;
+
+   efi_debugfs = debugfs_create_dir("efi", NULL);
+   if (IS_ERR_OR_NULL(efi_debugfs)) {
+   pr_warn("Could not create efi debugfs entry\n");
+   return;
+   }
+
+   for_each_efi_memory_desc(md) {
+   switch (md->type) {
+   case EFI_BOOT_SERVICES_CODE:
+   snprintf(name, sizeof(name), "boot_services_code%d",
+type_count[md->type]++);
+   break;
+   case EFI_BOOT_SERVICES_DATA:
+   snprintf(name, sizeof(name), "boot_services_data%d",
+type_count[md->type]++);
+   break;
+   default:
+   continue;
+   }
+
+   debugfs_blob[i].size = md->num_pages << EFI_PAGE_SHIFT;
+   debugfs_blob[i].data = memremap(md->phys_addr,
+   debugfs_blob[i].size,
+   MEMREMAP_WB);
+   if (!debugfs_blob[i].data) {
+   pr_warn("Error mapping %s\n", name);
+   continue;
+   }
+
+   debugfs_create_blob(name, 0400, efi_debugfs, _blob[i]);
+   i++;
+   if (i == EFI_DEBUGFS_MAX_BLOBS)
+   break;
+   }
+}
+#else
+static inline void efi_debugfs_init(void) {}
+#endif
+
 /*
  * We register the efi subsystem with the firmware subsystem and the
  * efivars subsystem with the efi subsystem, if the system was booted with
@@ -360,6 +414,9 @@ static int __init efisubsys_init(void)
goto err_remove_group;
}
 
+   if (efi_enabled(EFI_DBG))
+   efi_debugfs_init();
+
return 0;
 
 err_remove_group:
-- 
2.17.0.rc2

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] efi: Ignore unrealistically large option roms

2018-03-30 Thread Hans de Goede
setup_efi_pci() tries to save a copy of each PCI option ROM as this may
be necessary for the device driver for the PCI device to have access too.

On some systems the efi_pci_io_protocol_64's romimage and romsize fields
contain invalid data, which looks a bit like pointers pointing back into
other EFI code or data. Interpreting these pointers as romsize leads to
a very large value and if we then try to alloc this amount of memory to
save a copy the alloc call fails.

This leads to a "Failed to alloc mem for rom" error being printed on the
EFI console for each PCI device.

This commit avoids the printing of these errors, by checking romsize
before doing the alloc and if it is larger then 256M silently ignore the
ROM fields instead of trying to alloc mem and fail.

Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 arch/x86/boot/compressed/eboot.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 886a9115af62..f744b037d3cd 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -230,7 +230,13 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct 
pci_setup_rom **__rom)
if (status != EFI_SUCCESS)
return status;
 
-   if (!pci->romimage || !pci->romsize)
+   /*
+* Some firmwares contain EFI function pointers at the place where the
+* romimage and romsize fields are supposed to be. Typically the EFI
+* code is mapped at high addresses, translating to an unrealistically
+* large romsize. We reject any roms over 256M in size to catch this.
+*/
+   if (!pci->romimage || !pci->romsize || pci->romsize > 0x1000)
return EFI_INVALID_PARAMETER;
 
size = pci->romsize + sizeof(*rom);
-- 
2.17.0.rc2

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Regression from efi: call get_event_log before ExitBootServices

2018-03-13 Thread Hans de Goede

Hi,

On 12-03-18 22:02, Ard Biesheuvel wrote:

On 12 March 2018 at 19:55, Thiebaud Weksteen  wrote:

On Mon, Mar 12, 2018 at 7:33 PM Jeremy Cline  wrote:


On 03/12/2018 02:29 PM, Thiebaud Weksteen wrote:

On Mon, Mar 12, 2018 at 6:30 PM Ard Biesheuvel <

ard.biesheu...@linaro.org>

wrote:


On 12 March 2018 at 17:01, Jeremy Cline  wrote:

On 03/12/2018 10:56 AM, Ard Biesheuvel wrote:

On 12 March 2018 at 14:30, Jeremy Cline  wrote:

On 03/12/2018 07:08 AM, Ard Biesheuvel wrote:

On 10 March 2018 at 10:45, Thiebaud Weksteen 

wrote:

On Fri, Mar 9, 2018 at 5:54 PM Jeremy Cline 

wrote:



On Fri, Mar 09, 2018 at 10:43:50AM +, Thiebaud Weksteen

wrote:

Thanks a lot for trying out the patch!

Please don't modify your install at this stage, I think we are

hitting a

firmware bug and that would be awesome if we can fix how we are

handling it.

So, if we reach that stage in the function it could either be

that:

* The allocation did not succeed, somehow, but the firmware

still

returned

EFI_SUCCEED.
* The size requested is incorrect (I'm thinking something like a

1G of

log). This would be due to either a miscalculation of log_size

(possible)

or; the returned values of GetEventLog are not correct.
I'm sending a patch to add checks for these. Could you please

apply and

retest?
Again, thanks for helping debugging this.



No problem, thanks for the help :)



With the new patch:



Locating the TCG2Protocol
Calling GetEventLog on TCG2Protocol
Log returned
log_location is not empty
log_size != 0
log_size < 1M
Allocating memory for storing the logs
Returned from memory allocation
Copying log to new location



And then it hangs. I added a couple more print statements:



diff --git a/drivers/firmware/efi/libstub/tpm.c

b/drivers/firmware/efi/libstub/tpm.c

index ee3fac109078..1ab5638bc50e 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -148,8 +148,11 @@ void

efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)

  efi_printk(sys_table_arg, "Copying log to new

location\n");



  memset(log_tbl, 0, sizeof(*log_tbl) + log_size);
+   efi_printk(sys_table_arg, "Successfully memset log_tbl to

0\n");

  log_tbl->size = log_size;
+   efi_printk(sys_table_arg, "Set log_tbl->size\n");
  log_tbl->version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
+   efi_printk(sys_table_arg, "Set log_tbl-version\n");
  memcpy(log_tbl->log, (void *) first_entry_addr,

log_size);



  efi_printk(sys_table_arg, "Installing the log into the

configuration table\n");


and it's hanging at "memset(log_tbl, 0, sizeof(*log_tbl) +

log_size);"


Thanks. Well, it looks like the memory that is supposedly

allocated

is not

usable. I'm thinking this is a firmware bug.
Ard, would you agree on this assumption? Thoughts on how to

proceed?




I am rather puzzled why the allocate_pool() should succeed and the
subsequent memset() should fail. This does not look like an issue

that

is intimately related to TPM2 support, rather an issue in the

firmware

that happens to get tickled after the change.

Would you mind trying replacing EFI_LOADER_DATA with
EFI_BOOT_SERVICES_DATA in the allocate_pool() call?


Replacing EFI_LOADER_DATA with EFI_BOOT_SERVICES_DATA still hangs at

the

memset() call.



Could you try the following please? (attached as well in case gmail

mangles it)


diff --git a/drivers/firmware/efi/libstub/tpm.c
b/drivers/firmware/efi/libstub/tpm.c
index 2298560cea72..30d960a344b7 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -70,6 +70,8 @@ void
efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
 size_t log_size, last_entry_size;
 efi_bool_t truncated;
 void *tcg2_protocol;
+   unsigned long num_pages;
+   efi_physical_addr_t log_tbl_alloc;

 status = efi_call_early(locate_protocol, _guid, NULL,
 _protocol);
@@ -104,9 +106,12 @@ void
efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
 }

 /* Allocate space for the logs and copy them. */
-   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
-   sizeof(*log_tbl) + log_size,
-   (void **) _tbl);
+   num_pages = DIV_ROUND_UP(sizeof(*log_tbl) + log_size,

EFI_PAGE_SIZE);

+   status = efi_call_early(allocate_pages,
+   EFI_ALLOCATE_ANY_PAGES,
+   EFI_LOADER_DATA,
+   num_pages,
+   _tbl_alloc);

 if (status != EFI_SUCCESS) {
 efi_printk(sys_table_arg,
@@ -114,6 +119,7 @@ void
efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
 return;
 }

+   log_tbl = 

Re: Regression from efi: call get_event_log before ExitBootServices

2018-03-13 Thread Hans de Goede

Hi,

On 12-03-18 20:55, Thiebaud Weksteen wrote:

On Mon, Mar 12, 2018 at 7:33 PM Jeremy Cline  wrote:


On 03/12/2018 02:29 PM, Thiebaud Weksteen wrote:

On Mon, Mar 12, 2018 at 6:30 PM Ard Biesheuvel <

ard.biesheu...@linaro.org>

wrote:


On 12 March 2018 at 17:01, Jeremy Cline  wrote:

On 03/12/2018 10:56 AM, Ard Biesheuvel wrote:

On 12 March 2018 at 14:30, Jeremy Cline  wrote:

On 03/12/2018 07:08 AM, Ard Biesheuvel wrote:

On 10 March 2018 at 10:45, Thiebaud Weksteen 

wrote:

On Fri, Mar 9, 2018 at 5:54 PM Jeremy Cline 

wrote:



On Fri, Mar 09, 2018 at 10:43:50AM +, Thiebaud Weksteen

wrote:

Thanks a lot for trying out the patch!

Please don't modify your install at this stage, I think we are

hitting a

firmware bug and that would be awesome if we can fix how we are

handling it.

So, if we reach that stage in the function it could either be

that:

* The allocation did not succeed, somehow, but the firmware

still

returned

EFI_SUCCEED.
* The size requested is incorrect (I'm thinking something like a

1G of

log). This would be due to either a miscalculation of log_size

(possible)

or; the returned values of GetEventLog are not correct.
I'm sending a patch to add checks for these. Could you please

apply and

retest?
Again, thanks for helping debugging this.



No problem, thanks for the help :)



With the new patch:



Locating the TCG2Protocol
Calling GetEventLog on TCG2Protocol
Log returned
log_location is not empty
log_size != 0
log_size < 1M
Allocating memory for storing the logs
Returned from memory allocation
Copying log to new location



And then it hangs. I added a couple more print statements:



diff --git a/drivers/firmware/efi/libstub/tpm.c

b/drivers/firmware/efi/libstub/tpm.c

index ee3fac109078..1ab5638bc50e 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -148,8 +148,11 @@ void

efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)

  efi_printk(sys_table_arg, "Copying log to new

location\n");



  memset(log_tbl, 0, sizeof(*log_tbl) + log_size);
+   efi_printk(sys_table_arg, "Successfully memset log_tbl to

0\n");

  log_tbl->size = log_size;
+   efi_printk(sys_table_arg, "Set log_tbl->size\n");
  log_tbl->version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
+   efi_printk(sys_table_arg, "Set log_tbl-version\n");
  memcpy(log_tbl->log, (void *) first_entry_addr,

log_size);



  efi_printk(sys_table_arg, "Installing the log into the

configuration table\n");


and it's hanging at "memset(log_tbl, 0, sizeof(*log_tbl) +

log_size);"


Thanks. Well, it looks like the memory that is supposedly

allocated

is not

usable. I'm thinking this is a firmware bug.
Ard, would you agree on this assumption? Thoughts on how to

proceed?




I am rather puzzled why the allocate_pool() should succeed and the
subsequent memset() should fail. This does not look like an issue

that

is intimately related to TPM2 support, rather an issue in the

firmware

that happens to get tickled after the change.

Would you mind trying replacing EFI_LOADER_DATA with
EFI_BOOT_SERVICES_DATA in the allocate_pool() call?


Replacing EFI_LOADER_DATA with EFI_BOOT_SERVICES_DATA still hangs at

the

memset() call.



Could you try the following please? (attached as well in case gmail

mangles it)


diff --git a/drivers/firmware/efi/libstub/tpm.c
b/drivers/firmware/efi/libstub/tpm.c
index 2298560cea72..30d960a344b7 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -70,6 +70,8 @@ void
efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
 size_t log_size, last_entry_size;
 efi_bool_t truncated;
 void *tcg2_protocol;
+   unsigned long num_pages;
+   efi_physical_addr_t log_tbl_alloc;

 status = efi_call_early(locate_protocol, _guid, NULL,
 _protocol);
@@ -104,9 +106,12 @@ void
efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
 }

 /* Allocate space for the logs and copy them. */
-   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
-   sizeof(*log_tbl) + log_size,
-   (void **) _tbl);
+   num_pages = DIV_ROUND_UP(sizeof(*log_tbl) + log_size,

EFI_PAGE_SIZE);

+   status = efi_call_early(allocate_pages,
+   EFI_ALLOCATE_ANY_PAGES,
+   EFI_LOADER_DATA,
+   num_pages,
+   _tbl_alloc);

 if (status != EFI_SUCCESS) {
 efi_printk(sys_table_arg,
@@ -114,6 +119,7 @@ void
efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
 return;
 }

+   log_tbl = (struct linux_efi_tpm_eventlog *)(unsigned

long)log_tbl_alloc;

 

Re: Regression from efi: call get_event_log before ExitBootServices

2018-03-09 Thread Hans de Goede

Hi,

On 08-03-18 18:26, Jeremy Cline wrote:

On 03/08/2018 11:50 AM, Hans de Goede wrote:



Hi,

On 07-03-18 12:34, Javier Martinez Canillas wrote:





Are you also able to read the TPM event logs?

$ hexdump /sys/kernel/security/tpm0/binary_bios_measurements


Yes for me that outputs a lot of hex :)


For me, /sys/kernel/security/tmp0 doesn't exist on 4.15.6 or 4.16 with
the patch reverted.


Hmm, have you re-enabled the TPM in the BIOS?


The UEFI firmware does some measurements and so does shim. So you should
have some event logs. What version of shim are you using? And also would
be good to know if it's the same shim version that Jeremy is using.


That is a very good question, I'm using: shim-ia32-13-0.7.x86_64, which is
the last version for F27 AFAICT.


All my tablet has installed is shim-0.8-10.x86_64, no shim-ia32.


Yes my bad, although if the kernel changes break booting on systems
without the shim that is still good to know and something which
we probably ought to fix.


But Jeremy's tablet might very well be not using the shim at all, as
I manually installed Fedora 25 on the tablet he now has, before Fedora
supported
machines with 32 bit EFI. I then later did a "dnf distro-sync" to
Fedora-27.

Jeremy might also very well still be booting using a grub binary I build
manually back then, without any shim being involved.

Jeremy what does efibootmgr -v output on your device ?


# efibootmgr -v
BootCurrent: 0003
Timeout: 4 seconds
BootOrder: 0003,,0001,2001,2002,2003
Boot* Android X64 OS
HD(1,GPT,215e6cf3-e97d-4735-9c4e-7338c8f5a645,0x800,0x32000)/File(\EFI\BOOT\bootx64.efi)RC
Boot0001* Internal EFI Shell
FvVol(a881d567-6cb0-4eee-8435-2e72d33e45b5)/FvFile(c57ad6b7-0515-40a8-9d21-551652854e37)RCM&".
Boot0003* Fedora
HD(1,GPT,215e6cf3-e97d-4735-9c4e-7338c8f5a645,0x800,0x32000)/File(\EFI\fedora\grubx64.efi)
Boot2001* EFI USB DeviceRC
Boot2002* EFI DVD/CDROM RC
Boot2003* EFI Network   RC
Boot8087* Udm
FvVol(a881d567-6cb0-4eee-8435-2e72d33e45b5)/FvFile(9a9ab4c1-ee1b-488b-b300-24544a7bd418)

I think you're right about it using the old grub binary. I'm
embarrassingly unfamiliar with both UEFI and grub, but I'm guessing you
set the location of grub.cfg at compile time? When I boot
\EFI\fedora\grubx64.efi, it's pulling the grub.cfg from
\EFI\redhat\grub.cfg.


Ah yes, so I did not build my own grub I took one from RHEL as that had
32 bit UEFI support before Fedora got it and as I was lazy I copied the
32 bit binary over the 64 bit one, so don't let the filename fool you.

What you could do is install grub2-efi-ia32 from the Fedora 27 repos
and then use efibootmgr to add an entry pointing to \EFI\fedora\grubia32.efi
note that one will look at \EFI\fedora\grub.cfg .

Then see if the problem persists. A second step would be to also install
shim-ia32 and point to that...

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Regression from efi: call get_event_log before ExitBootServices

2018-03-08 Thread Hans de Goede



Hi,

On 07-03-18 12:34, Javier Martinez Canillas wrote:

On 03/07/2018 12:10 PM, Hans de Goede wrote:





Both according to the BIOS and to the /sys/class/tpm/tpm0/device/description
file it is a TPM 2.0.



I see, so you can choose enabling the TPM 1.2 or TPM 2.0 device? At least that's
the case on my X1 Carbon laptop. I've both a hardware TPM 1.2 and a firmware TPM
2.0 that's implemented as an Intel ME application (AFAIU).


This device only has the firmware TPM 2.0 implementation.




I'm actually amazed that this machine has a TPM at all, a quick internet
search shows that it is a software implemented TPM running as part of the
TXE firmware.



A quick search suggests that it comes with Windows 10?


Yes, it comes with Windows 10.


For start, can you please check if you can boot a v4.16-rcX kernel with the
TPM device enabled? That way we will know that at least that it consistently
fails on this machine and is not and isolated issue.


I just tried and v4.16-rc3 boots fine for me, repeatedly.



That's an interesting data point.


I guess Jeremy's model may actually have something in the TPM log


I don't think so. The UEFI firmware already does some measurements and also
does shim. So you *should* have some logs.


while my TPM log is empty... Is there anyway to make sure the TPM
log has some info to retreive?



Are you also able to read the TPM event logs?

$ hexdump /sys/kernel/security/tpm0/binary_bios_measurements


Yes for me that outputs a lot of hex :)


The UEFI firmware does some measurements and so does shim. So you should
have some event logs. What version of shim are you using? And also would
be good to know if it's the same shim version that Jeremy is using.


That is a very good question, I'm using: shim-ia32-13-0.7.x86_64, which is
the last version for F27 AFAICT.

But Jeremy's tablet might very well be not using the shim at all, as
I manually installed Fedora 25 on the tablet he now has, before Fedora supported
machines with 32 bit EFI. I then later did a "dnf distro-sync" to Fedora-27.

Jeremy might also very well still be booting using a grub binary I build
manually back then, without any shim being involved.

Jeremy what does efibootmgr -v output on your device ?

Regards,

Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Regression from efi: call get_event_log before ExitBootServices

2018-03-07 Thread Hans de Goede

Hi,

On 07-03-18 09:41, Thiebaud Weksteen wrote:

Hi,

Thanks for testing and sending this report! This patch relies heavily on
the functions exposed by the firmware. My first guess would be that some of
these may not be implemented correctly by the manufacturer.

Could you share more information on this specific device?


I've the same device as Jeremy, but I just tried a 4.16-rc3 kernel
and I'm not seeing this problem, BIOS settings all default (I loaded
the BIOS defaults to make sure).


Do you have any link to the manufacturer website (I found [1] but it is
based on an ARM CPU)?
Do you have the option to update your firmware? Is a copy of the firmware
available from the manufacturer?


This is a really cheap Windows tablet which was given away for free in
the Netherlands with some home-schooling language courses, or something
similar.

Both mine and Jeremy tablets come from a website in the Netherlands
where people can buy/sell used goods.

Most relevant for this discussion I guess is that this device is
based on a Bay Trail Z3735G SoC, on which according to the internets:
https://embedded.communities.intel.com/thread/7868

The TPM 2.0 it contains is implemented as part of the TXE firmware.

Since I cannot reproduce I'm thinking that maybe Jeremy actually has
some log messages in the TPM log, where as mine is empty.  Is there a
way to make sure some messages are in there?

Regards,

Hans




On your side, I assume no error message got displayed on the screen when
booting. Would you be able to try to boot in an UEFI shell [2] and execute
the command "dh -v"?

Thanks,
Thiebaud

[1] https://www.gp-electronic.nl/product/7inchtablet
[2]
https://wiki.archlinux.org/index.php/Unified_Extensible_Firmware_Interface#UEFI_Shell

On Tue, Mar 6, 2018 at 5:00 PM Jeremy Cline  wrote:


Hi folks,



Commit 33b6d03469b2 ("efi: call get_event_log before ExitBootServices")
causes my GP-electronic T701 tablet to hang when booting. Reverting the
patch series or hiding the TPM in the BIOS fixes the problem.



I've never fiddled with TPMs before so I'm not sure what what debugging
information to provide. It's got an Atom Z3735G and the UEFI firmware is
InsydeH20 version BYT70A.YNCHENG.WIN.007.




Regards,
Jeremy

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: efi/reboot: Fall back to original power-off method if EFI_RESET_SHUTDOWN returns

2017-06-21 Thread Hans de Goede

HI,

On 23-04-17 14:36, Hans de Goede wrote:

Commit 44be28e9dd98 ("x86/reboot: Add EFI reboot quirk for ACPI Hardware
Reduced flag") sets pm_power_off to efi_power_off() when the
acpi_gbl_reduced_hardware flag is set.

According to its commit message this is necessary because: "BayTrail-T
class of hardware requires EFI in order to powerdown and reboot and no
other reliable method exists"

But I have a Bay Trail CR tablet where the EFI_RESET_SHUTDOWN call does
not work, it simply returns without doing anything (AFAICT).

So it seems that some Bay Trail devices must use EFI for power-off, while
for others only ACPI works.

Note that efi_power_off() only gets used if the platform code defines
efi_poweroff_required() and that returns true, this currently only ever
happens on x86.

Since on the devices which need ACPI for power-off the EFI_RESET_SHUTDOWN
call simply returns, this patch makes the efi-reboot code remember the
old pm_power_off handler and if EFI_RESET_SHUTDOWN returns it falls back
to calling that.

This seems preferable to dmi-quirking our way out of this, since there
are likely quite a few devices suffering from this.

Cc: Mark Salter <msal...@redhat.com>
Signed-off-by: Hans de Goede <hdego...@redhat.com>


What is the status of this patch ? It has had 2 somewhat favorable
reviews and then things went silent ?

Regards,

Hans




---
  drivers/firmware/efi/reboot.c | 12 +++-
  1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/reboot.c b/drivers/firmware/efi/reboot.c
index 62ead9b..7117e2d 100644
--- a/drivers/firmware/efi/reboot.c
+++ b/drivers/firmware/efi/reboot.c
@@ -5,6 +5,8 @@
  #include 
  #include 
  
+void (*orig_pm_power_off)(void);

+
  int efi_reboot_quirk_mode = -1;
  
  void efi_reboot(enum reboot_mode reboot_mode, const char *__unused)

@@ -51,6 +53,12 @@ bool __weak efi_poweroff_required(void)
  static void efi_power_off(void)
  {
efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
+   /*
+* The above call should not return, if it does fall back to
+* the original power off method (typically ACPI poweroff).
+*/
+   if (orig_pm_power_off)
+   orig_pm_power_off();
  }
  
  static int __init efi_shutdown_init(void)

@@ -58,8 +66,10 @@ static int __init efi_shutdown_init(void)
if (!efi_enabled(EFI_RUNTIME_SERVICES))
return -ENODEV;
  
-	if (efi_poweroff_required())

+   if (efi_poweroff_required()) {
+   orig_pm_power_off = pm_power_off;
pm_power_off = efi_power_off;
+   }
  
  	return 0;

  }


--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] efi/reboot: Fall back to original power-off method if EFI_RESET_SHUTDOWN returns

2017-04-23 Thread Hans de Goede
Commit 44be28e9dd98 ("x86/reboot: Add EFI reboot quirk for ACPI Hardware
Reduced flag") sets pm_power_off to efi_power_off() when the
acpi_gbl_reduced_hardware flag is set.

According to its commit message this is necessary because: "BayTrail-T
class of hardware requires EFI in order to powerdown and reboot and no
other reliable method exists"

But I have a Bay Trail CR tablet where the EFI_RESET_SHUTDOWN call does
not work, it simply returns without doing anything (AFAICT).

So it seems that some Bay Trail devices must use EFI for power-off, while
for others only ACPI works.

Note that efi_power_off() only gets used if the platform code defines
efi_poweroff_required() and that returns true, this currently only ever
happens on x86.

Since on the devices which need ACPI for power-off the EFI_RESET_SHUTDOWN
call simply returns, this patch makes the efi-reboot code remember the
old pm_power_off handler and if EFI_RESET_SHUTDOWN returns it falls back
to calling that.

This seems preferable to dmi-quirking our way out of this, since there
are likely quite a few devices suffering from this.

Cc: Mark Salter <msal...@redhat.com>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 drivers/firmware/efi/reboot.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/reboot.c b/drivers/firmware/efi/reboot.c
index 62ead9b..7117e2d 100644
--- a/drivers/firmware/efi/reboot.c
+++ b/drivers/firmware/efi/reboot.c
@@ -5,6 +5,8 @@
 #include 
 #include 
 
+void (*orig_pm_power_off)(void);
+
 int efi_reboot_quirk_mode = -1;
 
 void efi_reboot(enum reboot_mode reboot_mode, const char *__unused)
@@ -51,6 +53,12 @@ bool __weak efi_poweroff_required(void)
 static void efi_power_off(void)
 {
efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
+   /*
+* The above call should not return, if it does fall back to
+* the original power off method (typically ACPI poweroff).
+*/
+   if (orig_pm_power_off)
+   orig_pm_power_off();
 }
 
 static int __init efi_shutdown_init(void)
@@ -58,8 +66,10 @@ static int __init efi_shutdown_init(void)
if (!efi_enabled(EFI_RUNTIME_SERVICES))
return -ENODEV;
 
-   if (efi_poweroff_required())
+   if (efi_poweroff_required()) {
+   orig_pm_power_off = pm_power_off;
pm_power_off = efi_power_off;
+   }
 
return 0;
 }
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   >