Discussion:
Switch boot entry by power-on reason
(too old to reply)
hede
2024-07-21 09:20:01 UTC
Permalink
Hi list,

does anybody know if it's possible to switch the boot menu entry to boot based on the reason the PC was powered on?

Say for example the following challenge:

- start Windows if someone powers it on via the power button
- start Linux if the system was powered on via LAN or a bios timer event

This would enable some general PC to also function as a remote backup PC. The user of the PC wants to start Windows if he powers it on via the Power Button. But additionally to that there is a timer event starting the PC at night for remote backups running at that time and the backup solution is for Linux.

I tried to find a solution using grub, systemd-boot, rEFInd and even the Windows Boot Manager with no success. It seems none of the famous boot managers is able to switch the boot entry based on the power up reason given by the UEFI.

Technically it should be possible, as dmidecode can show the reason:
Handle 0x0001, DMI type 1, 27 bytes
System Information
...
Wake-up Type: LAN Remote
vs.
Wake-up Type: Power Switch

(the first one was powered on via Intel AMT, the second one by the power switch, as an example)

It seems still no one has implemented that?

(the next problem would be to have a working Secure Boot + TPM hard disk decrypt operation for both systems... but this one is of no interest if there is no reason)

best regards
hede
Thomas Schmitt
2024-07-21 09:50:01 UTC
Permalink
Hi,
Post by hede
Handle 0x0001, DMI type 1, 27 bytes
System Information
...
Wake-up Type: LAN Remote
vs.
Wake-up Type: Power Switch
The statement in man dmidecode "DMI (some say SMBIOS)" caused me to search
for "GRUB SMBIOS" which yields:
https://www.gnu.org/software/grub/manual/grub/html_node/smbios.html

This looks like a low-level user interface to
https://en.wikipedia.org/wiki/System_Management_BIOS

Diving into
https://codesearch.debian.net/search?q=package%3Admidecode+Wake-up+Type
leads me to
https://sources.debian.org/src/dmidecode/3.6-1/dmidecode.c/?hl=4498#L4498
which lets me guess that your answer is in
smbios --type 1 --get-byte 24
with the possible values told by function dmi_system_wake_up_type()
https://sources.debian.org/src/dmidecode/3.6-1/dmidecode.c/?hl=513#L513

Consider to explore this in the GRUB shell and (if needed) to find
somebody who can help to develop a smart configuration which makes use of
the result to offer different boot menus.
(I am not sure whether we have the expertise here. As last resort, i'd
ask at mailinglist grub-***@gnu.org in the hope that the experts are
in helpful mood. It's not a very harsh environment there.)


Have a nice day :)

Thomas
David
2024-07-21 10:50:01 UTC
Permalink
Post by Thomas Schmitt
Post by hede
Handle 0x0001, DMI type 1, 27 bytes
System Information
...
Wake-up Type: LAN Remote
vs.
Wake-up Type: Power Switch
The statement in man dmidecode "DMI (some say SMBIOS)" caused me to search
https://www.gnu.org/software/grub/manual/grub/html_node/smbios.html
This looks like a low-level user interface to
https://en.wikipedia.org/wiki/System_Management_BIOS
Diving into
https://codesearch.debian.net/search?q=package%3Admidecode+Wake-up+Type
leads me to
https://sources.debian.org/src/dmidecode/3.6-1/dmidecode.c/?hl=4498#L4498
which lets me guess that your answer is in
smbios --type 1 --get-byte 24
with the possible values told by function dmi_system_wake_up_type()
https://sources.debian.org/src/dmidecode/3.6-1/dmidecode.c/?hl=513#L513
Consider to explore this in the GRUB shell and (if needed) to find
somebody who can help to develop a smart configuration which makes use of
the result to offer different boot menus.
Hi, well it looks like Thomas has done most of the work and provided most of
the solution. Assuming that is the case, I suggest that an easy way to activate
a different menu entry would be to use the value found by the above research to
change the value of 'default' in grub.cfg

So your manually written grub.cfg. would contain something like the below lines
in addition to whatever other content you need to boot the machine.

smbios --type 1 --get-byte 24 --set result
if [ "${result}" == "REPLACEME" ] ; then
default=1
else
default=2
fi

Hopefully all that remains is to use the above information to figure out
the actual value needed to replace my REPLACEME placeholder.
And change '1' and '2' to match whatever menuentry you would like to
activate.

Don't be discouraged by all the junk that the autogenerated grub.cfg
contains these days, most of it is not necessary. I have never had any
trouble ignoring it completely and just writing something simple in the style
of grub1. That way you can take advantage of the very useful scripting
language that grub2 provides, and hopefully make it do exactly what you want.
David
2024-07-22 01:40:01 UTC
Permalink
Post by David
Don't be discouraged by all the junk that the autogenerated grub.cfg
contains these days, most of it is not necessary. I have never had any
trouble ignoring it completely and just writing something simple in the style
of grub1. That way you can take advantage of the very useful scripting
language that grub2 provides, and hopefully make it do exactly what you want.
"All the junk" that you're ignoring will be the code that implements
properly what you're trying to do with Grub. Overall, it's a hack, but
you don't need to hack on top of the hack.
[snip]
The hack is booting Windows after starting via the power button.
Oh, thanks for the extra info, when writing my answer I forgot the
requirement to boot into Windows. That's something I really don't
care to know about any more.

grub2 autogenerated files are full of un-necessary junk and are
so complicated that users are expected to only interact with them
indirectly through constrained configfiles and are deterred from
instead just writing the code themselves for what they want to
accomplish, which was the old way. grub2 is very cool and supports
functions for example, but unfortunately the autogenerated files dont
take advantage of that feature, so they are hard to read and break
the "do not repeat yourself" principles, with the same UUIDs for
example appearing in multiple places.

Here
https://paste.debian.net/1323940/
is an example of what my grub.cfg files look like, for anyone who
is interested in different approaches. I maintain them manually
and disable or deflect the autogeneration.
The approach is to use grub1 style stanzas created by functions.
The magnetic disk layout is 3 unencrypted primary partitions boot,
X and Y, and one more partition is encrypted LVM containing bootable
logical volumes A,B,C,D,E. Partition table is MSDOS format.
I prefer the use of functions because it makes it easy to manually
edit them and see useful diffs in version control.

This probably would be more helpful if I wrote a blog post about
it or contributed to the code, but I'm busy with other projects and
don't have time to do that, so I'm just throwing it out here for
anyone interested. The example file is from a laptop
running Debian 11, so it's a bit out of date, but I wanted to show
a simple one. My hardware isn't "modern", I don't care because
it meets my needs.

Thanks to the regular contributors here for sharing your
knowledge, I learn a lot, and so I occasionally try to give back.
But I know that others here are more capable or more dedicated
to doing that than I am, so I am mostly a reader not a writer here.
hede
2024-07-29 16:30:04 UTC
Permalink
Hello David and Thomas,
Post by David
...
So your manually written grub.cfg. would contain something like the below lines
in addition to whatever other content you need to boot the machine.
smbios --type 1 --get-byte 24 --set result
if [ "${result}" == "REPLACEME" ] ; then
default=1
else
default=2
fi
Many thanks, it works :-)

Here for me the result is either 5 or 6 and I can switch between the boot entries by manipulating the default entry via this smbios command. The best thing with this solution is, that it only sets the default value so the user can override it manually by choosing some other entry. The timeout remains.

Btw: This computer is one of those where Windows is constantly kicking out Grub from the EFI Boot Manager. After booting Windows there is no longer any grub in the EFI Boot Manager and the PC starts Windows only.

But that's not Microsofts fault here, it's the BIOS vendors fault (HP/AMI) as this UEFI removes all EFI Boot Manager entries except the Default one. I tried to add several additional entries and they all get removed on next boot. So if Grub adds itself, the Windows boot entry gets removed. So Windows adds itself again on next boot (which I think is quite reasonable to do). So then Grub gets removed again.

The solution is to force Windows to add Grub as its own Bootloader with (in a Windows Admin Shell):

bcdedit /set {bootmgr} path \EFI\debian\shimx64.efi

There are plenty of articles in the Internet how to do so correctly. Afterwards Windows wants to install Grub if Grub gets removed from UEFI. ;-)
Post by David
Hopefully all that remains is to use the above information to figure out
the actual value needed to replace my REPLACEME placeholder.
Boot the PC via all the different methods and for every one run in the Grub shell:
smbios --type 1 --get-byte 24
This returns the value of the current startup type / boot reason.

Many thanks
hede
Thomas Schmitt
2024-07-29 16:50:01 UTC
Permalink
Hi,
Post by hede
Post by David
smbios --type 1 --get-byte 24 --set result
Many thanks, it works :-)
\o/\o/ So the community and its resources are not that useless \o/\o/


Have a nice day :)

Thomas

Loading...