Hi, efiboot cannot load the kernel properly on some machines if booted from CD-ROM. In that case boot fails with a message like follow:
booting cd0a:..... [359648read symbols: Unknown error: code 255 As far as Asou and my test, this happens on hosts on VMware ESXi 6.7, 7.0 and asou's physical machine. The problem happens because efiboot calls ReadBlocks function with an unaligned pointer for medias which requires an aligned pointer. When efiboot loads a kernel, the pointer becomes unaligned since there is an ELF section located at unaligned place in CD-ROM. Previously our kernel didn't have such a section but it does after switching lld as the default linker. For test, let me show sample commands which creates a bootable cdrom image for EFI: mkdir -p efiboot/EFI/BOOT cp /usr/mdec/BOOTX64.EFI efiboot/EFI/BOOT makefs -M 1m -m 1m -t msdos -o fat_type=12,sectors_per_cluster=1 \ efiboot.img efiboot mkdir -p cd-dir/etc cp bsd.rd cd-dir/ echo "set image bsd.rd" > cd-dir/etc/boot.conf makefs -t cd9660 -o 'rockridge,bootimage=i386;/usr/mdec/cdbr,no-emul-boot,allow-multidot,bootimage=efi;efiboot.img,no-emul-boot' \ boot.iso cd-dir the diff is to fix the problem. ok? Index: sys/arch/amd64/stand/efiboot/efidev.c =================================================================== RCS file: /disk/cvs/openbsd/src/sys/arch/amd64/stand/efiboot/efidev.c,v retrieving revision 1.32 diff -u -p -r1.32 efidev.c --- sys/arch/amd64/stand/efiboot/efidev.c 9 Dec 2020 18:10:18 -0000 1.32 +++ sys/arch/amd64/stand/efiboot/efidev.c 10 Mar 2021 10:58:35 -0000 @@ -84,7 +84,7 @@ efid_init(struct diskinfo *dip, void *ha static EFI_STATUS efid_io(int rw, efi_diskinfo_t ed, u_int off, int nsect, void *buf) { - u_int blks, lba, i_lblks, i_tblks, i_nblks; + u_int i, blks, lba, i_lblks, i_tblks, i_nblks; EFI_STATUS status = EFI_SUCCESS; static u_char *iblk = NULL; static u_int iblksz = 0; @@ -127,10 +127,29 @@ efid_io(int rw, efi_diskinfo_t ed, u_int min(nsect, i_lblks) * DEV_BSIZE); } if (i_nblks > 0) { - status = EFI_CALL(ed->blkio->ReadBlocks, - ed->blkio, ed->mediaid, lba, - ed->blkio->Media->BlockSize * (i_nblks / blks), - buf + (i_lblks * DEV_BSIZE)); + /* + * Pass the buffer directly to the EFI function only if + * the buffer is properly aligned as the media requires + */ + if (ed->blkio->Media->IoAlign > 1 && + ((UINTN)buf + i_lblks * DEV_BSIZE) + % ed->blkio->Media->IoAlign == 0) + status = EFI_CALL(ed->blkio->ReadBlocks, + ed->blkio, ed->mediaid, lba, + ed->blkio->Media->BlockSize * (i_nblks / + blks), buf + i_lblks * DEV_BSIZE); + else { + for (i = 0; i < i_nblks; i += blks) { + status = EFI_CALL(ed->blkio->ReadBlocks, + ed->blkio, ed->mediaid, + lba + i / blks, + ed->blkio->Media->BlockSize, iblk); + if (EFI_ERROR(status)) + break; + memcpy(buf + i * DEV_BSIZE, iblk, + ed->blkio->Media->BlockSize); + } + } if (EFI_ERROR(status)) goto on_eio; } @@ -160,10 +179,30 @@ efid_io(int rw, efi_diskinfo_t ed, u_int ed->blkio->Media->BlockSize, iblk); } if (i_nblks > 0) { - status = EFI_CALL(ed->blkio->WriteBlocks, - ed->blkio, ed->mediaid, lba, - ed->blkio->Media->BlockSize * (i_nblks / blks), - buf + (i_lblks * DEV_BSIZE)); + /* + * Pass the buffer directly to the EFI function only if + * the buffer is properly aligned as the media requires + */ + if (ed->blkio->Media->IoAlign > 1 && + ((UINTN)buf + i_lblks * DEV_BSIZE) + % ed->blkio->Media->IoAlign == 0) + status = EFI_CALL(ed->blkio->WriteBlocks, + ed->blkio, ed->mediaid, lba, + ed->blkio->Media->BlockSize * (i_nblks / + blks), buf + i_lblks * DEV_BSIZE); + else { + for (i = 0; i < i_nblks; i += blks) { + memcpy(iblk, buf + i * DEV_BSIZE, + ed->blkio->Media->BlockSize); + status = EFI_CALL( + ed->blkio->WriteBlocks, + ed->blkio, ed->mediaid, + lba + i / blks, + ed->blkio->Media->BlockSize, iblk); + if (EFI_ERROR(status)) + break; + } + } if (EFI_ERROR(status)) goto on_eio; }