On 01/16/19 03:16, Gary Lin wrote:
> On Tue, Jan 15, 2019 at 12:58:10PM +0100, Laszlo Ersek wrote:
>> On 01/15/19 10:45, Gary Lin wrote:
>>> In some cases, such as MD RAID1 in Linux, the bootloader may be in a
>>> nested EFI system partition partition. For example, sda1 and sdb1 are
>>> combined as md0 and the first partition of md0, md0p1, is an EFI system
>>> partition. Then, the bootloader can be located by the following device
>>> paths:
>>>
>>> PCI()/SATA(sda)/Partition(sda1)/Partition(md0p1)/File(bootloader.efi)
>>> PCI()/SATA(sdb)/Partition(sdb1)/Partition(md0p1)/File(bootloader.efi)
>>
>> How does edk2 recognize the nested partition md0p1 in the first place?
>>
>> I would assume that the "outer" partitions (sda1, sdb1) start with some
>> kind of MD RAID1 header that allows Linux to combine sda1 and sdb1 into
>> md0p1. How does edk2 get past that header?
>>
>> Hmmm... based on
>> <https://raid.wiki.kernel.org/index.php/RAID_superblock_formats>, does
>> Linux use "footers" instead of "headers"?
>>
> See the "Sub-versions of the version-1 superblock" section:
> <https://raid.wiki.kernel.org/index.php/RAID_superblock_formats#Sub-versions_of_the_version-1_superblock>
> 
> For MD 0.9 and 1.0, the metadata is stored in the end of the disk, and
> those partitions, nested or not, are just like the normal partitions, so
> the firmare can see them without the knowledge of MD metadata. MD 1.1
> and 1.2 would be a different story because those two use "headers".
> 
> Anyway, I have tested RAID1 with MD 1.0 and OVMF actually appended md0p1
> in the device path. I only need to iterate the nested partitions in the
> match function to make my boot option work.

Thanks for the explanation! I'll let Ray review the change.
Laszlo

>>>
>>> To make the boot option more resilient, we may create a boot option with
>>> the short-form device path like "Partition(md0p1)/File(bootloader.efi)".
>>>
>>> However, BmMatchPartitionDevicePathNode() only matched the first
>>> partition node and ignored the nested partitions, so the firmware would
>>> refuse to load bootloader.efi since "Partition(md0p1)" doesn't match
>>> either "Partition(sda1)" or "Partition(sda2)".
>>>
>>> This commit modifies BmMatchPartitionDevicePathNode() to iterate all
>>> nested partitions so that the above boot option could work.
>>>
>>> Cc: Ruiyu Ni <ruiyu...@intel.com>
>>> Cc: Star Zeng <star.z...@intel.com>
>>> Cc: Jian J Wang <jian.j.w...@intel.com>
>>> Cc: Hao Wu <hao.a...@intel.com>
>>> Contributed-under: TianoCore Contribution Agreement 1.1
>>> Signed-off-by: Gary Lin <g...@suse.com>
>>> ---
>>>  .../Library/UefiBootManagerLib/BmBoot.c       | 37 ++++++++++++-------
>>>  1 file changed, 23 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c 
>>> b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
>>> index 6a23477eb873..8354c2af674b 100644
>>> --- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
>>> +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
>>> @@ -1995,21 +1995,30 @@ BmMatchPartitionDevicePathNode (
>>>      return FALSE;
>>>    }
>>>  
>>> -  //
>>> -  // See if the harddrive device path in blockio matches the orig Hard 
>>> Drive Node
>>> -  //
>>> -  Node = (HARDDRIVE_DEVICE_PATH *) BlockIoDevicePath;
>>> +  do {
>>> +    //
>>> +    // See if the harddrive device path in blockio matches the orig Hard 
>>> Drive Node
>>> +    //
>>> +    Node = (HARDDRIVE_DEVICE_PATH *) BlockIoDevicePath;
>>>  
>>> -  //
>>> -  // Match Signature and PartitionNumber.
>>> -  // Unused bytes in Signature are initiaized with zeros.
>>> -  //
>>> -  return (BOOLEAN) (
>>> -    (Node->PartitionNumber == HardDriveDevicePath->PartitionNumber) &&
>>> -    (Node->MBRType == HardDriveDevicePath->MBRType) &&
>>> -    (Node->SignatureType == HardDriveDevicePath->SignatureType) &&
>>> -    (CompareMem (Node->Signature, HardDriveDevicePath->Signature, sizeof 
>>> (Node->Signature)) == 0)
>>> -    );
>>> +    //
>>> +    // Match Signature and PartitionNumber.
>>> +    // Unused bytes in Signature are initiaized with zeros.
>>> +    //
>>> +    if ((Node->PartitionNumber == HardDriveDevicePath->PartitionNumber) &&
>>> +        (Node->MBRType == HardDriveDevicePath->MBRType) &&
>>> +        (Node->SignatureType == HardDriveDevicePath->SignatureType) &&
>>> +        (CompareMem (Node->Signature, HardDriveDevicePath->Signature, 
>>> sizeof (Node->Signature)) == 0)) {
>>> +      return TRUE;
>>> +    }
>>> +
>>> +    // See if a nested partition exists
>>> +    BlockIoDevicePath = NextDevicePathNode (BlockIoDevicePath);
>>> +  } while (!IsDevicePathEnd (BlockIoDevicePath) &&
>>> +           (DevicePathType (BlockIoDevicePath) == MEDIA_DEVICE_PATH) &&
>>> +           (DevicePathSubType (BlockIoDevicePath) == MEDIA_HARDDRIVE_DP));
>>> +
>>> +  return FALSE;
>>>  }
>>>  
>>>  /**
>>>
>>
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel
>>

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to