The natural solution would be to use a network server from which those machines can get information on which system to boot. On the teacher's machine it is trivial to do in a certain directory:
echo linux > bootsel; python3 -m http.server
or
echo windows > bootsel; python3 -m http.server
The problem is how it can be handled in GRUB. I spent some time checking the documentation, searching the web, and finally discussing it with ChatGPT.
Grub may load the file from the HTTP server. The commands below display the contents of such a file (I assume that the server has IP 10.0.2.2 - like in the case of a QEMU-emulated machine):
insmod http
insmod net
insmod efinet
cat (http,10.0.2.2:8000)/bootsel
The question is, how can we use the contents of this downloaded file?
Grub does not allow storing that content in a variable so that it could be later compared with constants.
Theoretically, the standard solution should be getting the whole grub configuration from the server and using it via:
configfile (http,10.0.2.2:8000)/bootsel
Such an approach is, however, insecure. Just imagine what could happen if somebody injects a malicious grub configuration.
After some further experimenting, I have found the right solution. Possible boot options should be stored in files on the students' machines:
echo windows > /opt/boot_win
echo debian > /opt/boot_debian
echo ubuntu > /opt/boot_ubuntu
Then we should add getting the file from the server and setting the default grub menu entry.
That is achieved by creating the /etc/grub.d/04_network file with the following contents (you may need to adjust the menu entry numbers):
#!/bin/sh
exec tail -n +3 $0
# Be careful not to change the 'exec tail' line above.
insmod http
insmod net
insmod efinet
net_bootp
if cmp (http,10.0.2.2:8000)/bootsel /opt/boot_win; then
set default=2
fi
if cmp (http,10.0.2.2:8000)/bootsel /opt/boot_debian; then
set default=3
fi
# Ubuntu is the default menu entry 0, so I don't need to handle it there
The attributes of the file should be the same as of other files in /etc/grub.d. Of course, update-grub must be run after the above file is created.
Please note, that the selected approach still enables manual selecting of the booted system in the GRUB menu. It only changes the default system booted without the manual selection.
If the HTTP server is not started, the default menu entry will be used after some delay.