diff mbox series

[U-Boot,v4,4/5] efi_loader: disk: install FILE_SYSTEM_PROTOCOL only if available

Message ID 20191007055939.17093-5-takahiro.akashi@linaro.org
State Accepted, archived
Commit 867400677cda0fac4a411f1549fe3a61bb5ed172
Delegated to: Heinrich Schuchardt
Headers show
Series efi_loader: disk: install FILE_SYSTEM_PROTOCOL to whole disk | expand

Commit Message

AKASHI Takahiro Oct. 7, 2019, 5:59 a.m. UTC
In the current implementation, EFI_SIMPLEFILE_SYSTEM_PROTOCOL is always
installed to all the partitions even if some of them may house no file
system.

With this patch, that protocol will be installed only if any file system
exists.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 lib/efi_loader/efi_disk.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

Comments

Heinrich Schuchardt Oct. 22, 2019, 8:29 p.m. UTC | #1
The patch

commit 867400677cda0fac4a411f1549fe3a61bb5ed172
efi_loader: disk: install FILE_SYSTEM_PROTOCOL only if available

breaks booting my Pine A64 LTS board via iPXE and GRUB. But I assume
this is not at the base of the problem.

My iSCSI drive is partitioned like this:

Device        Boot    Start      End  Sectors  Size Id Type
pine-a64-lts1          2048   194559   192512   94M ef EFI   vfat
pine-a64-lts2 *      194560  2148351  1953792  954M 83 Linux ext2
pine-a64-lts3       2148352 25585663 23437312 11.2G 83 Linux ext4
pine-a64-lts4      25585664 67106815 41521152 19.8G 83 Linux ext4

Looking at the debug output below the following questions arise:

Why is ext2 not recognized as a file system?
Why is the system crashing when trying to read 1024 blocks from the ext4
partition?

.config contains CONFIG_FS_EXT4=y

EFI: efi_bl_bind: handle 00000000b9f94560, interface 00000000b8e9f7f8
EFI: efi_bl_read: read 'efiblk#0', from block 0, 1 blocks
EFI: Call: io->read_blocks( io, io->media->media_id, (u64)blknr,
(efi_uintn_t)blkcnt * (efi_uintn_t)io->media->block_size, buffer)
EFI: 0 returned by io->read_blocks( io, io->media->media_id, (u64)blknr,
(efi_uintn_t)blkcnt * (efi_uintn_t)io->media->block_size, buffer)
EFI: efi_bl_read: r = 0
EFI: efi_bl_bind: block device 'efiblk#0' created
EFI: efi_bl_read: read 'efiblk#0', from block 2048, 1 blocks
EFI: Call: io->read_blocks( io, io->media->media_id, (u64)blknr,
(efi_uintn_t)blkcnt * (efi_uintn_t)io->media->block_size, buffer)
EFI: 0 returned by io->read_blocks( io, io->media->media_id, (u64)blknr,
(efi_uintn_t)blkcnt * (efi_uintn_t)io->media->block_size, buffer)
EFI: efi_bl_read: r = 0
lib/efi_loader/efi_disk.c(279) efi_fs_exists: 0 returned by
fs_set_blk_dev_with_part(desc, 1)
EFI: efi_bl_read: read 'efiblk#0', from block 194560, 1 blocks
EFI: Call: io->read_blocks( io, io->media->media_id, (u64)blknr,
(efi_uintn_t)blkcnt * (efi_uintn_t)io->media->block_size, buffer)
EFI: 0 returned by io->read_blocks( io, io->media->media_id, (u64)blknr,
(efi_uintn_t)blkcnt * (efi_uintn_t)io->media->block_size, buffer)
EFI: efi_bl_read: r = 0
EFI: efi_bl_read: read 'efiblk#0', from block 195584, 1024 blocks
EFI: Call: io->read_blocks( io, io->media->media_id, (u64)blknr,
(efi_uintn_t)blkcnt * (efi_uintn_t)io->media->block_size, buffer)
EFI: 0 returned by io->read_blocks( io, io->media->media_id, (u64)blknr,
(efi_uintn_t)blkcnt * (efi_uintn_t)io->media->block_size, buffer)
EFI: efi_bl_read: r = 0
** Unrecognized filesystem type **
lib/efi_loader/efi_disk.c(279) efi_fs_exists: -1 returned by
fs_set_blk_dev_with_part(desc, 2)
EFI: efi_bl_read: read 'efiblk#0', from block 2148352, 1 blocks
EFI: Call: io->read_blocks( io, io->media->media_id, (u64)blknr,
(efi_uintn_t)blkcnt * (efi_uintn_t)io->media->block_size, buffer)
EFI: 0 returned by io->read_blocks( io, io->media->media_id, (u64)blknr,
(efi_uintn_t)blkcnt * (efi_uintn_t)io->media->block_size, buffer)
EFI: efi_bl_read: r = 0
EFI: efi_bl_read: read 'efiblk#0', from block 2149376, 1024 blocks
EFI: Call: io->read_blocks( io, io->media->media_id, (u64)blknr,
(efi_uintn_t)blkcnt * (efi_uintn_t)io->media->block_size, buffer)

"Synchronous Abort" handler, esr 0x02000000

elr: ffffffff8c0a6028 lr : ffffffff8c0a6000 (reloc)
elr: 0000000000000028 lr : 0000000000000000
x0 : 00000000b9f918f8 x1 : 00000000b9f31004
x2 : 00000000b9f918f8 x3 : 00000000b9f918f8
x4 : 00000000b9f918f8 x5 : 00000000b9f918f8
x6 : 00000000b9f918f8 x7 : 0000000000000000
x8 : 00000000b9f918f8 x9 : 00000000b8ea1038
x10: 0000000000000001 x11: 0000000019100bb0
x12: 0000000000000000 x13: 0000000000000001
x14: 0000000000000002 x15: 0000000000000003
x16: 00000000000000c8 x17: 00000000b9f918f8
x18: 00000000b9f31c30 x19: 00000000b9f918f8
x20: 00000000b8e9ddd0 x21: 00000000b8e99000
x22: 00000000b9f31008 x23: 00000000b9f3105a
x24: 00000000b9f31068 x25: 00000000b9f31110
x26: 0000000000000000 x27: 0000000000000000
x28: 0000000000000000 x29: 00000000b9f31160

Code: ea000011 ea000000 ea000013 eafffffe (e3a00001)

Looks like we jumped into nowhere land:

All code
========
    0:   ea000011        ands    x17, x0, x0
    4:   ea000000        ands    x0, x0, x0
    8:   ea000013        ands    x19, x0, x0
    c:   eafffffe        bics    x30, xzr, xzr, ror #63
   10:*  e3a00001        .inst   0xe3a00001 ; undefined          <--
trapping instruction

Best regards

Heinrich
AKASHI Takahiro Oct. 23, 2019, 10:30 a.m. UTC | #2
On Tue, Oct 22, 2019 at 10:29:09PM +0200, Heinrich Schuchardt wrote:
> The patch
> 
> commit 867400677cda0fac4a411f1549fe3a61bb5ed172
> efi_loader: disk: install FILE_SYSTEM_PROTOCOL only if available
> 
> breaks booting my Pine A64 LTS board via iPXE and GRUB. But I assume
> this is not at the base of the problem.
> 
> My iSCSI drive is partitioned like this:
> 
> Device        Boot    Start      End  Sectors  Size Id Type
> pine-a64-lts1          2048   194559   192512   94M ef EFI   vfat
> pine-a64-lts2 *      194560  2148351  1953792  954M 83 Linux ext2
> pine-a64-lts3       2148352 25585663 23437312 11.2G 83 Linux ext4
> pine-a64-lts4      25585664 67106815 41521152 19.8G 83 Linux ext4
> 
> Looking at the debug output below the following questions arise:
> 
> Why is ext2 not recognized as a file system?
> Why is the system crashing when trying to read 1024 blocks from the ext4
> partition?

Try the workaround attached below.
It seems that some fields, particularly log2blksz, in blk_dev held by
ext_fs(of ext_filesystem in fs/ext4/ext4fs.c) are not initialized.

I think that ext4's initialization code should be reworked.

-Takahiro Akashi

diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 861fcaf3747f..0792e53b32c6 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -337,6 +337,12 @@ static efi_status_t efi_disk_add_dev(
 			       diskobj->dp);
 	if (ret != EFI_SUCCESS)
 		return ret;
+	if (!part) {
+		char buf[10];
+
+		sprintf(buf, "%d:%d", dev_index, part);
+		fs_set_blk_dev(if_typename, buf, FS_TYPE_ANY);
+	}
 	if (part >= 1 && efi_fs_exists(desc, part)) {
 		diskobj->volume = efi_simple_file_system(desc, part,
 							 diskobj->dp);
Heinrich Schuchardt Oct. 24, 2019, 3:26 a.m. UTC | #3
On 10/23/19 12:30 PM, AKASHI Takahiro wrote:
> On Tue, Oct 22, 2019 at 10:29:09PM +0200, Heinrich Schuchardt wrote:
>> The patch
>>
>> commit 867400677cda0fac4a411f1549fe3a61bb5ed172
>> efi_loader: disk: install FILE_SYSTEM_PROTOCOL only if available
>>
>> breaks booting my Pine A64 LTS board via iPXE and GRUB. But I assume
>> this is not at the base of the problem.
>>
>> My iSCSI drive is partitioned like this:
>>
>> Device        Boot    Start      End  Sectors  Size Id Type
>> pine-a64-lts1          2048   194559   192512   94M ef EFI   vfat
>> pine-a64-lts2 *      194560  2148351  1953792  954M 83 Linux ext2
>> pine-a64-lts3       2148352 25585663 23437312 11.2G 83 Linux ext4
>> pine-a64-lts4      25585664 67106815 41521152 19.8G 83 Linux ext4
>>
>> Looking at the debug output below the following questions arise:
>>
>> Why is ext2 not recognized as a file system?
>> Why is the system crashing when trying to read 1024 blocks from the ext4
>> partition?
>
> Try the workaround attached below.
> It seems that some fields, particularly log2blksz, in blk_dev held by
> ext_fs(of ext_filesystem in fs/ext4/ext4fs.c) are not initialized.
>
> I think that ext4's initialization code should be reworked.

Thanks for looking into this.

The error is in efi_bl_bind() (lib/efi_driver/efi_block_device.c). I
missed to use the block size of the block IO protocol to initialize
desc->blksz and desc->log2blksz.

Our FAT driver takes the sector size from the boot sector in
get_fs_info() (fs/fat/fat.c) and ignores the block descriptor which will
lead to errors if the logical sector size does not match the physical
sector size.

Best regards

Heinrich
diff mbox series

Patch

diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 9007a5f77f3d..861fcaf3747f 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -9,6 +9,7 @@ 
 #include <blk.h>
 #include <dm.h>
 #include <efi_loader.h>
+#include <fs.h>
 #include <part.h>
 #include <malloc.h>
 
@@ -262,6 +263,27 @@  efi_fs_from_path(struct efi_device_path *full_path)
 	return handler->protocol_interface;
 }
 
+/**
+ * efi_fs_exists() - check if a partition bears a file system
+ *
+ * @desc:	block device descriptor
+ * @part:	partition number
+ * Return:	1 if a file system exists on the partition
+ *		0 otherwise
+ */
+static int efi_fs_exists(struct blk_desc *desc, int part)
+{
+	if (fs_set_blk_dev_with_part(desc, part))
+		return 0;
+
+	if (fs_get_type() == FS_TYPE_ANY)
+		return 0;
+
+	fs_close();
+
+	return 1;
+}
+
 /*
  * Create a handle for a partition or disk
  *
@@ -315,7 +337,7 @@  static efi_status_t efi_disk_add_dev(
 			       diskobj->dp);
 	if (ret != EFI_SUCCESS)
 		return ret;
-	if (part >= 1) {
+	if (part >= 1 && efi_fs_exists(desc, part)) {
 		diskobj->volume = efi_simple_file_system(desc, part,
 							 diskobj->dp);
 		ret = efi_add_protocol(&diskobj->header,