I was using GRUB to UEFI PXE boot or UEFI HTTP boot a Linux Live OS (made by Ubuntu Bionic), I used same grub.cfg etc for them, it worked well under UEFI PXE boot, but failed in UEFI HTTP boot.
Then I found something interesting about in which phase who did http access.
- in UEFI PXE boot, the HTTP access log is like this:
"GET /liveos/focal/kernel HTTP/1.1" 200 11780639 "-" "GRUB 2.06-2ubuntu14.1" "GET /liveos/focal/initrd HTTP/1.1" 200 61697204 "-" "GRUB 2.06-2ubuntu14.1" "GET /liveos/focal/squashfs HTTP/1.1" 200 218095923 "-" "Wget" So GRUB loaded kernel and initrd, then initrd used wget to load squashfs. OK, it makes sense.
- however, when in UEFI HTTP boot, the HTTP access log is like this:
"GET /bootx64.efi HTTP/1.1" 200 955941 "-" "UefiHttpBoot/1.0" "GET /grubx64.efi HTTP/1.1" 200 1493150 "-" "UefiHttpBoot/1.0" "GET /grub/grub.cfg HTTP/1.1" 200 1823 "-" "UefiHttpBoot/1.0" "GET /liveos/focal/kernel HTTP/1.1" 200 11780639 "-" "UefiHttpBoot/1.0" "GET /liveos/focal/initrd HTTP/1.1" 200 449680 "-" "UefiHttpBoot/1.0" So GRUB use the http agent "UefiHttpBoot/1.0" to load kernel and initrd. Unfortunately the access log shows that server did not respond full size of data to the UEFI HTTP boot client. Full size response should be like 61697204, but now are just 449680.
Here comes the questions:
- Where is the http agent "UefiHttpBoot/1.0" implemented? in the firmware?
- Why does GRUB2 not use same logic as in UEFI PXE boot, i.e., using its own http agent to get initrd?
EDIT: it looks like that, in UEFI HTTP boot, from the beginning, it is the http agent "UefiHttpBoot/1.0" that loading bootx64.efi, so "UefiHttpBoot/1.0" should comes from the firmware, however, it should then pass execution control to the bootx64.efi(GRUB2), then GRUB2 should use its own http tool to read initrd, but actually it is not, why? Seems like the UEFI HTTP boot cooperates with Linux boot protocol in some degree.
EDIT: more info:
[ 1.947449] Unpacking initramfs... [ 1.950954] Initramfs unpacking failed: junk in compressed archive or [ 1.943484] Unpacking initramfs... [ 1.946991] Initramfs unpacking failed: broken padding The grub.cfg is like this: (please remember that it works well in UEFI PXE boot):
set default=0 set timeout=1 menuentry boot_liveos { linux (http,100.0.0.101)/liveos/focal/kernel nomodeset ro root=squash:http://100.0.0.101/liveos/focal/squashfs ip=::::hostname:BOOTIF ip6=off overlayroot=tmpfs overlayroot_cfgdisk=disabled apparmor=0 ds=nocloud console=tty0 console=ttyS1,115200 BOOTIF=01-${net_default_mac} initrd (http,100.0.0.101)/liveos/focal/initrd } PS, not only focal, but also bionic, jammy, all same issue. I have also tried different GRUB2 versions, from 20200320.0 to 20230222.0, all same issue.
The problem becomes that something wrong in the "UefiHttpBoot/1.0", it can not accept large data.
EDIT: if this is an firmware issue, then is there anyway to tell grub to load http files by itself?
EDIT: continue to investigate the issue.
$ strings bootx64.efi |grep UefiHttpBoot UefiHttpBoot/1.0 $ strings grubx64.efi |grep UefiHttpBoot UefiHttpBoot/1.0 The GRUB2 binaries embeds the http agent string "UefiHttpBoot/1.0", so the execution control should have been passed to GRUB2, it is just that GRUB2 continues to use same agent string to do http access. I have checked source code at http://archive.ubuntu.com/ubuntu/pool/main/g/grub2-unsigned/grub2-unsigned_2.06.orig.tar.xz (parent page is https://packages.ubuntu.com/focal-updates/grub-efi-amd64) but have not found the agent string, but found a constant var PACKAGE_STRING, probably which is defined when building the binaries.
http_establish (struct grub_file *file, grub_off_t offset, int initial) { http_data_t data = file->data; grub_uint8_t *ptr; int i; struct grub_net_buff *nb; grub_err_t err; nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE + sizeof ("GET ") - 1 + grub_strlen (data->filename) + sizeof (" HTTP/1.1\r\nHost: ") - 1 + grub_strlen (file->device->net->server) + sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n") - 1 + sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX" "-\r\n\r\n")); if (!nb) return grub_errno; Found the http agent string in GRUB2's debian patched source: http://archive.ubuntu.com/ubuntu/pool/main/g/grub2-unsigned/grub2-unsigned_2.06-2ubuntu14.1.debian.tar.xz