> On Feb 5, 2016, at 10:36 AM, Ryan Harkin <[email protected]> wrote:
> 
> Hi Laszlo,
> 
> On 5 February 2016 at 17:19, Laszlo Ersek <[email protected]> wrote:
>> On 02/05/16 17:35, Ryan Harkin wrote:
>>> Hello all,
>>> 
>>> I'm having a problem that is platform specific, but perhaps more of a
>>> generic problem.
>>> 
>>> When ARM's Juno board boots, not all devices are connected.  The first
>>> boot creates the boot variables and sets their order, meaning that we
>>> get the following list on the first attempt:
>>> 
>>>  EFI Misc Device
>>>  EFI Misc Device 1
>>>  EFI Internal Shell
>>> 
>>> Intel BDS then attempts to boot from one of the devices and ends up in
>>> Shell.  After exiting Shell, the Intel BDS console GUI comes up.
>>> Selecting the Boot Manager option shows more devices being connected
>>> and the list becomes longer:
>>> 
>>>   EFI Misc Device
>>>   EFI Misc Device 1
>>>   EFI Internal Shell
>>>   EFI Hard Drive
>>>   EFI Network
>>> 
>>> Subsequent boots will never attempt to boot from Hard Drive or Network
>>> because Shell will always succeed.  That is not good.
>>> 
>>> Leif has a patch in his working tree that solves this problem [1] by
>>> making the platform call BdsLibConnectAll() at init time.  So now, the
>>> first time boot order looks sane:
>>> 
>>>   EFI Misc Device
>>>   EFI Misc Device 1
>>>   EFI Hard Drive
>>>   EFI Network
>>>   EFI Internal Shell
>>> 
>>> However, then the board is booting, the "EFI Network" fails to boot
>>> the first time and so the board drops back to Shell again:
>>> 
>>>  Warning: LAN9118 Driver in stopped state
>>>  Link timeout in auto-negotiation.
>>>  Lan9118: Auto Negociation not supported.
>>>  EhcExecTransfer: transfer failed with 2
>>>  EhcControlTransfer: error - Device Error, transfer - 2
>>>  Buffer: EFI Hard Drive
>>>  Booting EFI Misc Device
>>>  Booting EFI Misc Device 1
>>>  Booting EFI Hard Drive
>>>  Booting EFI Network
>>>  Warning: LAN9118 Driver not initialized
>>>  Link timeout in auto-negotiation.
>>>  Lan9118: Auto Negociation not supported.
>>>  Booting EFI Internal Shell
>>> 
>>> Exiting Shell drops the user back to the Intel BDS UI.  Selecting
>>> "Continue" then succeeds in booting from the EFI Network:
>>> 
>>>  Booting EFI Misc Device
>>>  Booting EFI Misc Device 1
>>>  Booting EFI Hard Drive
>>>  Booting EFI Network
>>>  ..MnpFreeTxBuf: Duplicated recycle report from SNP.
>>>  MnpFreeTxBuf: Duplicated recycle report from SNP.
>>>  [snip repeated SNP errors]
>>> 
>>> If I duplicate the call to BdsLibConnectAll() [2], then boot works as
>>> expected.  On first boot, the boot order is created correctly and EFI
>>> Network pulls down a file and boots it.
>>> 
>>> I'm assuming that the 2nd call is connecting things that didn't
>>> connect the first time.  And from that, I suspect/guess that perhaps
>>> they didn't connect due to either ordering or timing.
>>> 
>>> Is there a recommended way to set the order things are connected?  Is
>>> it even possible to specify dependencies or order? And if so, how do
>>> we work out what the order should be?
>> 
>> I cannot give a coherent answer, just a few thoughts.
>> 
>> (1) I think BdsLibConnectAll() actually succeeds for the first time as
>> well. All devices are enumerated, all drivers are connected, aren't
>> they? The boot order is a separate question.
>> 
> 
> Yes, you're right, they are all connected because they all appear in
> the boot list.
> 
> 
>> (2) The network, the NIC, or the NIC driver are more probable suspects.
>> If I see right, you always have a misc / misc1 / hd / network sequence
>> of attempts, it's just that on the first few occasions, the network
>> fails. ("Link timeout in auto-negotiation".)
>> 
> 
> Correct.
> 
> 
>> (3) I think repeated BdsLibConnectAll() calls may only give more time to
>> the NIC to bring itself into working shape. What if you keep only one
>> BdsLibConnectAll(), and replace the second BdsLibConnectAll() with a
>> sizeable gBS->Stall()?
>> 
> 
> Eureka!  I replace the 2nd BdsLibConnectAll() with
> "gBS->Stall(500000);" (0.5 seconds) and this works every time also.
> 
> So time to negociate (sic) would seem like the culprit.  I suppose a
> 2nd BdsLibConnectAll() buys the NIC some time.
> 
> I'm left wondering if the "Boot EFI Network" option should actually be
> waiting for negotiation, however.  I'm sure it's common on first boot
> that the network needs a little time to negotiate.  I'll look into
> that.  Perhaps there is a setting or an override to tell it to be
> patient?
> 

This is either a bug in the driver, or a bug in the config of the PXE server. 

Thanks,

Andrew Fish

> 
>> (4) What the boot order should be can be influenced by the platform BDS
>> lib, in the PlatformBdsPolicyBehavior() function.
>> 
>> Namely, the BdsEntry() function in
>> "MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c" initializes the
>> "BootOptionList" variable to an empty list. Then it calls
>> PlatformBdsPolicyBehavior(), which takes "BootOptionList" as an
>> input/output parameter -- if it wishes, it can populate it.
>> 
>> In ArmVirtPkg and in OvmfPkg, we perform the following steps in
>> PlatformBdsPolicyBehavior():
>> 
>> (a) connect the console(s)
>> 
>> (b) BdsLibConnectAll()
>> 
>> (c) BdsLibEnumerateAllBootOption (BootOptionList) -- this relies on the
>> presence of all devices, from the previous step. This function (in
>> "IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c") has extensive
>> documentation in its leading comment.
>> 
>> It will enumerate everything sensible (modifying BootOrder as well I
>> think), and output a BootOptionList that contains all the possible boot
>> options, in a sane order. Sanity means, if I remember correctly, that
>> all options that existed previously and were referenced by BootOrder,
>> retain their positions at the front of the list, and any new
>> auto-detected boot options are tacked to the end.
>> 
>> (d) SetBootOrderFromQemu (BootOptionList) -- this is the really platform
>> specific part for massaging the boot order. We read through
>> BootOptionList -- we don't modify it --, do various calculations, and
>> then rewrite the BootOrder variable. Importantly, all Boot#### variables
>> that become *unreferenced* by BootOrder as a result of this, must be
>> deleted (otherwise they constitute a leak). Again, BootOptionList is not
>> modified.
>> 
>> (e) BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder") -- it
>> rebuilds BootOptionList from the new BootOrder contents. (We are again
>> in PlatformBdsPolicyBehavior(), where BootOptionList counts as
>> input/output.)
>> 
>> On a physical platform, I think you just go with (b) and (c), and then
>> let the user customize the boot order. Next time you boot, (c) will
>> respect that.
>> 
> 
> Excellent answer, thanks.  It looks like (c) is exactly the thing I'm
> looking for.  For example, make HDD boot before USB.  That sort of
> thing.
> 
> I'm quite happy that once the default boot order has been set that it
> stays that way unless the user changes it.  I don't (think I) want to
> customise the boot order after the initial boot.
> 
> 
>> There are further possibilities; there is a "boot mode" HOB with which
>> your low-level platform code can control your BDS policy, in order to
>> speed up things. See BdsLibGetBootMode() and the macros in
>> "MdePkg/Include/Pi/PiBootMode.h". Those macros are documented in one of
>> the PI spec volumes.
>> 
>> For example, I think BOOT_ASSUMING_NO_CONFIGURATION_CHANGES is meant to
>> be very fast (no need to connect all devices to all drivers), but such a
>> HOB must be produced by your own PEI phase somehow -- you must know for
>> example that the chassis was never opened while the machine was off.
>> 
>> FWIW, OVMF only uses BOOT_WITH_FULL_CONFIGURATION, and
>> BOOT_ON_S3_RESUME, and these two are differentiated in OVMF's PEI phase
>> by reading a CMOS register.
>> 
>> Anyway, I think what you need is:
>> - call BdsLibConnectAll() exactly once
>> - give that NIC more time (?)
>> - if you'd like to regenerate all possible boot options *at the end* of
>>  BootOrder that the user may have deleted (or have become available by
>>  installing new hardware), call BdsLibEnumerateAllBootOption() too.
>> 
> 
> Yes, that sounds about right.  I have concerns about the negotiation
> timing, but the boot order hacking sounds like what I'm looking for.
> 
> Thanks again,
> Ryan.
> 
> 
>> Laszlo
>> 
>>> 
>>> Regards,
>>> Ryan.
>>> 
>>> [1] 
>>> https://git.linaro.org/uefi/linaro-edk2.git/commitdiff/bfbd0ef1a182e1baa120f66ad2c6838ef48ff48c
>>> [2] 
>>> https://git.linaro.org/landing-teams/working/arm/edk2.git/commitdiff/25320ba4e447a843daaf7c603ec87afae3c2a120
>>> 
>> 
> _______________________________________________
> edk2-devel mailing list
> [email protected]
> https://lists.01.org/mailman/listinfo/edk2-devel

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to