On 01/22/13 01:17, David Woodhouse wrote:
> When I have a virtio disk attached to a qemu VM, it doesn't appear in
> the OVMF boot menu, so I can't boot from it. This is because the
> BdsGetBootTypeFromDevicePath() function in GenericBdsLib.c only works on
> the device path and isn't able to infer that 'PciRoot(0x0)/Pci(0x5,0x0)'
> is a virtio disk. It could be *any* PCI device, if the path is all
> you're looking at.
>
> Should the VirtioBlk driver actually be registering a *child* of the Pci
> device node, such as PciRoot(0x0)/Pci(0x5,0x0)/Virtio(0), so that we can
> automatically work out what it is from the path? Or is there a better
> way?

The virtio-blk driver implements the EFI_BLOCK_IO_PROTOCOL for
virtio-blk devices; that should be enough for enumerating the disk.

If, instead of selecting Boot Manager in the OVMF boot menu, you go to

  Boot Maintenance Manager
    Boot Options
      Add Boot Option

then in the File Explorer appearing there, something like

  PciRoot(0x0)/Pci(0x5,0x0)/HD(...)

shows up. (It can be navigated down to \EFI\BOOT\BOOTX64.EFI.)

The device path node that corresponds to the HD(...) substring is
constructed by code outside of the virtio-blk driver (on top of the
block IO protocol that virtio-blk produces). This HD(...) DP node is of
type MEDIA_DEVICE_PATH, subtype MEDIA_HARDDRIVE_DP (see
"DevPathToTextTable" and DevPathToTextHardDrive() in
"MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c").

The calls seem to advance as in:

PlatformBdsPolicyBehavior()        
[OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c]
  BdsLibEnumerateAllBootOption()   
[IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c]
    BdsGetBootTypeFromDevicePath()
  SetBootOrderFromQemu()           
[OvmfPkg/Library/PlatformBdsLib/QemuBootOrder.c]

BdsGetBootTypeFromDevicePath() seems to handle MEDIA_HARDDRIVE_DP. It
progresses through PciRoot(...) and Pci(...), and returns
BDS_EFI_MEDIA_HD_BOOT for type MEDIA_DEVICE_PATH, subtype
MEDIA_HARDDRIVE_DP.

However BdsLibEnumerateAllBootOption() chooses to ignore
BDS_EFI_MEDIA_HD_BOOT on purpose (unlike BDS_EFI_MESSAGE_SCSI_BOOT,
which BdsGetBootTypeFromDevicePath() returns for virtio-scsi devices).
See the comment on BdsLibEnumerateAllBootOption():

--------*--------
  4. Fixed BlockIo          - The boot option only points to a Fixed blockIo 
device,
                              like HardDisk.
                              These device should contain a *fixed* blockIo
                              protocol in their device handle.
                              BDS will skip fixed blockIo devices, and NOT
                              automatically create boot option for them. But BDS
                              will help to delete those fixed blockIo boot 
option,
                              whose description rule conflict with other 
auto-created
                              boot options.

  [...]

  This function will enumerate all possible boot device in the system, and
  automatically create boot options for Network, Shell, Removable BlockIo,
  and Non-BlockIo Simplefile devices.
--------*--------

Therefore the problem is not a missing child device path node; code
outside of virtio-blk appends the appropriate MEDIA_HARDDRIVE_DP node to
the device path. The problem is that BdsLibEnumerateAllBootOption()
skips MEDIA_HARDDRIVE_DP / BDS_EFI_MEDIA_HD_BOOT deliberately. I'm not
sure what the intent was.

(

  Later on, SetBootOrderFromQemu() would retrieve the fw_cfg boot order,
  translate the OpenFirmware device paths to UEFI device path prefixes,
  reorder the list of enumerated boot options against matching device
  path prefixes, and kill the rest of UEFI boot options. However
  BdsLibEnumerateAllBootOption() doesn't return a boot option for
  virtio-blk automatically, hence it doesn't matter if the fw_cfg boot
  order would favor it.

  Once a boot option for a virtio-blk device has been established
  manually (down to the BOOTX64.EFI file), and if it doesn't conflict
  with an auto-enumerated boot option, then it will be available to
  SetBootOrderFromQemu().

  (

    If you set DEBUG_VERBOSE / 0x00400000 in
    "gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel" in file
    "OvmfPkg/OvmfPkgX64.dsc", then the Match() function in
    "OvmfPkg/Library/PlatformBdsLib/QemuBootOrder.c" will log the boot
    options enumerated by BdsLibEnumerateAllBootOption() as it tries to
    match each OpenFirmware device path against them. Something like:

    SetBootOrderFromQemu: FwCfg:
    /pci@i0cf8/scsi@7/disk@0,0
    SetBootOrderFromQemu: FwCfg: <end>
    ParseOfwNode: DriverName="pci" UnitAddress="i0cf8" DeviceArguments=""
    ParseOfwNode: DriverName="scsi" UnitAddress="7" DeviceArguments=""
    ParseOfwNode: DriverName="disk" UnitAddress="0,0" DeviceArguments=""
    TranslateOfwPath: success: "PciRoot(0x0)/Pci(0x7,0x0)/HD("
    Match: against "PciRoot(0x0)/Pci(0x1,0x0)/Floppy(0x0)": no match
    Match: against "PciRoot(0x0)/Pci(0x1,0x0)/Floppy(0x1)": no match
    Match: against 
"MemoryMapped(0xB,0xDFC0E000,0xDFFBDFFF)/FvFile(C57AD6B7-0515-40A8-9D21-551652854E37)":
 no match
    Match: against 
"PciRoot(0x0)/Pci(0x7,0x0)/HD(2,GPT,A2146CB9-2947-4342-9528-D9F4369CBEF4,0x96800,0x31800)/\EFI\Boot\bootx64.efi":
 match
    TranslateOfwPath: no more nodes
    EmuVariablesUpdatedCallback
    Saved NV Variables to NvVars file
    SetBootOrderFromQemu: setting BootOrder: success

  )

)

Laszlo

------------------------------------------------------------------------------
Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
MVPs and experts. ON SALE this month only -- learn more at:
http://p.sf.net/sfu/learnnow-d2d
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to