diff --git a/README.md b/README.md index 95f8664..0ff51b0 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ I provide pre-compiled images ready for use. Standard GNU toolchain and a few files from gnuefi (included). [bootboot.efi](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.efi) (76k), [bootboot.rom](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.rom) (76k) -2. *x86_64-bios* BIOS and Multiboot (GRUB) compatible, OBSOLETE loader. +2. *x86_64-bios* BIOS, Multiboot (GRUB) and El Torito (CDROM) compatible, OBSOLETE loader. If you want to recompile this, you'll need fasm (not included). - [boot.bin](https://gitlab.com/bztsrc/bootboot/raw/master/boot.bin) (512 bytes, works as MBR and VBR too), [bootboot.bin](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.bin) (8k) + [boot.bin](https://gitlab.com/bztsrc/bootboot/raw/master/boot.bin) (512 bytes, works as MBR, VBR and CDROM boot record too), [bootboot.bin](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.bin) (8k, loaded by boot.bin, also BBS Expansion ROM and Multiboot compliant) 3. *aarch64-rpi* ARMv8 boot loader for Raspberry Pi 3 [bootboot.img](https://gitlab.com/bztsrc/bootboot/raw/master/bootboot.img) (27k) @@ -29,7 +29,7 @@ The protocol describes how to boot an ELF64 or PE32+ executable inside an initia into clean 64 bit mode, without using any configuration or even knowing the file system of initrd. On [BIOS](https://gitlab.com/bztsrc/bootboot/tree/master/x86_64-bios) based systems, the same image can be loaded via -Multiboot, chainload from MBR or VBR (GPT hybrid booting) or run as a BIOS Expansion ROM +Multiboot, chainload from MBR, VBR (GPT hybrid booting) and CDROM boot record, or run as a BIOS Expansion ROM (so not only the ramdisk can be in ROM, but the loader as well). On [UEFI machines](https://gitlab.com/bztsrc/bootboot/tree/master/x86_64-efi), it is a standard EFI OS Loader application. @@ -45,7 +45,7 @@ as if it were a monolitic kernel. And you can use your own file system for the i Note: BOOTBOOT is not a boot manager, it's a boot loader protocol. If you want an interactive boot menu, you should integrate that *before* a BOOTBOOT compatible loader is called. Like GRUB chainloading boot.bin (or loading bootboot.bin as a -kernel) or adding bootboot.efi to UEFI Boot Manager's menu for example. +multiboot "kernel" and initrd as a module) or adding bootboot.efi to UEFI Boot Manager's menu for example. Licence ------- @@ -105,7 +105,7 @@ Glossary * _initrd_: initial [ramdisk image](https://gitlab.com/bztsrc/bootboot/blob/master/README.md#installation) (probably in ROM or flash, or on a GPT boot partition at BOOTBOOT\INITRD, or it can occupy the whole partition, or can be loaded - over the network). It's format and whereabouts are not specified (the good part :-) ) and can be optionally gzip compressed. + over the network or as a GRUB module). It's format and whereabouts are not specified (the good part :-) ) and can be optionally gzip compressed. * _loader_: a native executable on the boot partition or in ROM. For multi-bootable disks more loader implementations can co-exists. @@ -354,11 +354,21 @@ Either the disk does not have a GPT, or there's no EFI System Partition nor any partition on it. Or the FAT file system is found but inconsistent, or doesn't have a BOOTBOOT directory. ``` -BOOTBOOT-PANIC: INITRD not found +BOOTBOOT-PANIC: Not 2048 sector aligned ``` -The loader could not find the initial ramdisk image on the boot partition. This message will be shown -even if you specify an alternative initrd file on EFI command line. +This error is only shown by bootboot.bin (and not by bootboot.efi or bootboot.img) and only when +booted from CDROM in El Torito "no emulation" mode, and the boot partition file system's +root directory is not 2048 bytes aligned or the cluster size is not multiple of 2048 +bytes. For FAT16 it depends on FAT table size and therefore on file system size. If you +see this message, increase the number of hidden sectors in BPB by 2. FAT32 file systems are +not affected. + +``` +BOOTBOOT-PANIC: Initrd not found +``` + +The loader could not find the initial ramdisk image on the boot partition. ``` BOOTBOOT-PANIC: Kernel not found in initrd diff --git a/aarch64-rpi/bootboot.c b/aarch64-rpi/bootboot.c index bd0d869..b815ad1 100644 --- a/aarch64-rpi/bootboot.c +++ b/aarch64-rpi/bootboot.c @@ -1197,7 +1197,7 @@ diskerr: } gotinitrd: if(initrd.ptr==NULL || initrd.size==0) { - puts("BOOTBOOT-PANIC: INITRD not found\n"); + puts("BOOTBOOT-PANIC: Initrd not found\n"); goto error; } #if INITRD_DEBUG diff --git a/boot.bin b/boot.bin index 0c0f4b9..f0af8dc 100644 Binary files a/boot.bin and b/boot.bin differ diff --git a/bootboot.bin b/bootboot.bin index d656524..b780333 100644 Binary files a/bootboot.bin and b/bootboot.bin differ diff --git a/bootboot.efi b/bootboot.efi index c613231..4ae15d8 100755 Binary files a/bootboot.efi and b/bootboot.efi differ diff --git a/bootboot.img b/bootboot.img index e494ee0..8e4442a 100755 Binary files a/bootboot.img and b/bootboot.img differ diff --git a/bootboot.rom b/bootboot.rom index 8fc6644..fc15d27 100644 Binary files a/bootboot.rom and b/bootboot.rom differ diff --git a/bootboot_spec_1st_ed.pdf b/bootboot_spec_1st_ed.pdf index 51e081b..3cefda0 100644 Binary files a/bootboot_spec_1st_ed.pdf and b/bootboot_spec_1st_ed.pdf differ diff --git a/x86_64-bios/README.md b/x86_64-bios/README.md index 9fbca98..ec34c96 100644 --- a/x86_64-bios/README.md +++ b/x86_64-bios/README.md @@ -5,7 +5,7 @@ See [BOOTBOOT Protocol](https://gitlab.com/bztsrc/bootboot) for common details. On [BIOS](http://www.scs.stanford.edu/05au-cs240c/lab/specsbbs101.pdf) based systems, the same image can be loaded via [Multiboot](https://www.gnu.org/software/grub/manual/multiboot/multiboot.html), -chainload from MBR or VBR (GPT hybrid booting via __boot.bin__) or run as a BIOS Expansion ROM +chainload from MBR, VBR (GPT hybrid booting) or from CDROM boot record via __boot.bin__, or run as a BIOS Expansion ROM (so not only the ramdisk can be in ROM, but the loader as well). Machine state @@ -16,16 +16,16 @@ IRQs masked. GDT unspecified, but valid, IDT unset. Code is running in superviso Installation ------------ -1. *BIOS disk*: copy __bootboot.bin__ to **_FS0:\BOOTBOOT\LOADER_**. You can place it inside your INITRD partition +1. *BIOS disk / cdrom*: copy __bootboot.bin__ to **_FS0:\BOOTBOOT\LOADER_**. You can place it inside your INITRD partition or outside of partition area as well (with `dd conv=notrunc oseek=x`). Finally install __boot.bin__ in the - master boot record (or in volume boot record if you have a boot manager), saving bootboot.bin's first sector's - LBA number in a dword at 0x1B0. The [mkboot](https://gitlab.com/bztsrc/bootboot/blob/master/x86_64-bios/mkboot.c) + El Torito Boot catalog with "no emulation" or in Master Boot Record (or in Volume Boot Record if you have a boot manager), + saving bootboot.bin's first sector's LBA number in a dword at 0x1B0. The [mkboot](https://gitlab.com/bztsrc/bootboot/blob/master/x86_64-bios/mkboot.c) utility will do that for you. 2. *BIOS ROM*: install __bootboot.bin__ in a **_BIOS Expansion ROM_**. 3. *GRUB*: specify __bootboot.bin__ as a Multiboot "kernel" in grub.cfg, or you can also chainload __boot.bin__. You can load -the initrd and the environment file as modules, if not given, they will be loaded from disk as usual. Example: +the initrd and the environment file as modules (in this order). If no modules given, they will be loaded from disk as usual. Example: ``` menuentry "MyKernel" { diff --git a/x86_64-bios/boot.asm b/x86_64-bios/boot.asm index 57c4d13..acd64c9 100644 --- a/x86_64-bios/boot.asm +++ b/x86_64-bios/boot.asm @@ -24,7 +24,8 @@ ;* DEALINGS IN THE SOFTWARE. ;* ;* This file is part of the BOOTBOOT Protocol package. -;* @brief 1nd stage loader, compatible with BIOS boot specification +;* @brief Stage1 loader, compatible with BIOS boot specification and +;* El Torito CD-ROM boot in "no emulation" mode ;* ;********************************************************************* @@ -75,7 +76,7 @@ bootboot_record: ;skip BPB area so that we can use this ;boot code on a FAT volume if needed db 05Ah-($-$$) dup 0 -.skipid: ;relocate our code to offset 600h +.skipid: ;relocate our code to offset 0h:600h cli xor ax, ax mov ss, ax @@ -97,22 +98,23 @@ bootboot_record: ;and copy ourselves to 600h mov cx, 100h repnz movsw + ;have to clear ds, because cs is set to 7c0 when booted from El Torito + push es + pop ds jmp 0:.start .start: ;save boot drive code mov byte [drive], dl ;initialize lba packet mov byte [lbapacket.size], 16 - mov byte [lbapacket.count], 58 mov byte [lbapacket.addr0+1], 08h ;to address 800h ;check for lba presistance - floppy not supported any more ;we use pendrive as removable media for a long time cmp dl, byte 80h jl .nolba - cmp dl, byte 84h - jae .nostage2err .notfloppy: mov ah, byte 41h mov bx, word 55AAh + clc int 13h jc .nolba cmp bx, word 0AA55h @@ -122,15 +124,42 @@ bootboot_record: .nolba: mov si, lbanotf jmp diefunc .lbaok: ;try to load stage2 - it's a continous area on disk - ;started at given sector with maximum size of 7400h bytes + ;started at given sector with maximum size of 7000h bytes mov si, stage2_addr mov di, lbapacket.sect0 + push bx push di + ;set up for hard-drive movsw movsw - movsw - movsw - call loadsectorfunc + mov byte [lbapacket.count], 56 + ;query cdrom status to see if it's a cdrom + mov ax, word 4B01h + mov dl, byte [drive] + mov si, spc_packet + mov byte [si], 13h + mov byte [si+2], 0h ;clear drive number + clc + int 13h + pop di + jc @f + ;some buggy BIOSes (like bochs') fail to set carry flag and ax properly + cmp byte [si+2], 0h + jz @f + ;lba=lba/4 + clc + rcr word [di+2], 1 + rcr word [di], 1 + clc + rcr word [di+2], 1 + rcr word [di], 1 + mov byte [lbapacket.count], 14 + ;load sectors +@@: mov ah, byte 42h + mov dl, byte [drive] + mov si, lba_packet + int 13h + pop bx ;do we have a 2nd stage loader? .chk: cmp word [ldr.header], bx @@ -138,15 +167,14 @@ bootboot_record: cmp byte [ldr.header+3], 0E9h jne .nostage2 ;invoke stage2 real mode code - print okay mov ax, [ldr.executor] add ax, ldr.executor+3 jmp ax .nostage2: ;try to load stage2 from a RAID mirror inc byte [drive] - cmp byte [drive], 84h - jl .lbaok + cmp byte [drive], 8Fh + jle .lbaok .nostage2err: mov si, stage2notf ;fall into the diefunc code @@ -168,18 +196,6 @@ diefunc: out 64h, al jmp far 0FFFFh:0 ;invoke BIOS POST routine -;loads an LBA sector -loadsectorfunc: - push bx - push si - mov ah, byte 42h - mov dl, byte [drive] - mov si, lba_packet - int 13h - pop si - pop bx - ret - ;ds:si zero terminated string to write printfunc: lodsb @@ -199,9 +215,10 @@ panic: db "-PANIC: ",0 lbanotf: db "LBA support",0 stage2notf: db "FS0:\BOOTBOOT\LOADER",0 found: db " not found",10,13,0 -okay: db "Booting LOADER...",10,13,0 drive: db 0 -lba_packet: db 01B0h-($-$$) dup 0 +lba_packet: db 16 dup 0 +spc_packet: db 13h dup 0 + db 01B0h-($-$$) dup 0 ;right before the partition table some data stage2_addr:dd 0FFFFFFFFh,0 ;1B0h 2nd stage loader address diff --git a/x86_64-bios/bootboot.asm b/x86_64-bios/bootboot.asm index 5f6782d..9ea5137 100644 --- a/x86_64-bios/bootboot.asm +++ b/x86_64-bios/bootboot.asm @@ -24,16 +24,16 @@ ;* DEALINGS IN THE SOFTWARE. ;* ;* This file is part of the BOOTBOOT Protocol package. -;* @brief Booting code for BIOS and MultiBoot +;* @brief Booting code for BIOS, MultiBoot and El Torito ;* -;* 2nd stage loader, compatible with GRUB and -;* BIOS boot specification 1.0.1 too (even expansion ROM). +;* Stage2 loader, compatible with GRUB and BIOS boot specification +;* 1.0.1 (even expansion ROM) and El Torito "no emulation" CDROM boot. ;* ;* memory occupied: 800-7C00 ;* ;* Memory map ;* 0h - 600h reserved for the system -;* 600h - 800h stage1 (MBR) +;* 600h - 800h stage1 (MBR/VBR, boot.bin) ;* 800h - 6C00h stage2 (this) ;* 6C00h - 7C00h stack ;* 8000h - 9000h bootboot structure @@ -420,6 +420,7 @@ getmemmap: repnz stosd cmp byte [hasinitrd], 0 jnz @f + mov dword [9000h], eax mov dword [bootboot.initrd_ptr], eax mov dword [bootboot.initrd_size], eax @@: mov dword [bootboot.initrd_ptr+4], eax @@ -763,19 +764,54 @@ prot_realmodefunc: prot_readsectorfunc: push eax push ecx - push edx push esi push edi - ;load 8 sectors (1 page) in low memory + ;load 8 sectors (1 page) or more in low memory mov dword [lbapacket.sect0], eax - mov dword [lbapacket.sect1], edx - mov dword [lbapacket.addr], 0A000h prot_realmode - mov ah, byte 42h + ;try all drives from bootdev-8F to support RAID mirror mov dl, byte [bootdev] - mov esi, lbapacket + mov byte [readdev], dl +.again: mov ax, word [lbapacket.count] + mov word [origcount], ax + ;query cdrom status to see if it's a cdrom + mov ax, word 4B01h + mov dl, byte [readdev] + mov esi, spc_packet + mov byte [si], 13h + mov byte [si+2], 0h ;clear drive number + clc int 13h - xor ebx, ebx + jc @f + ;some buggy BIOSes (like bochs') fail to set carry flag and ax properly + cmp byte [si+2], 0h + jz @f + ;use 2048 byte sectors instead of 512 if it's a cdrom + mov al, byte [lbapacket.sect0] + and al, 011b + or al, al + jz .cdok + ;this should never happen. + ; - GPT is loaded from PMBR, from LBA 0 (%4==0) + ; - ESP is at LBA 128 (%4==0) + ; - root dir is at LBA 172 (%4==0) for FAT16, and it's cluster aligned for FAT32 + ; - cluster size is multiple of 4 sectors + mov si, notcdsect + jmp real_diefunc +.cdok: shr dword [lbapacket.sect0], 2 + add word [lbapacket.count], 3 + shr word [lbapacket.count], 2 + mov byte [iscdrom], 1 +@@: mov dl, byte [readdev] + inc byte [readdev] + mov ah, byte 42h + mov esi, lbapacket + clc + int 13h + jnc @f + cmp byte [readdev], 08Fh + jle .again +@@: xor ebx, ebx mov bl, ah real_protmode pop edi @@ -785,12 +821,11 @@ prot_readsectorfunc: ;and copy to addr where it wanted to be (maybe in high memory) mov esi, dword [lbapacket.addr] xor ecx, ecx - mov cx, word [lbapacket.count] + mov cx, word [origcount] shl ecx, 7 repnz movsd pop edi @@: pop esi - pop edx pop ecx pop eax ret @@ -880,9 +915,14 @@ protmode_start: ; read GPT .getgpt: xor eax, eax - xor edx, edx xor edi, edi prot_readsector +if DEBUG eq 1 + cmp byte [iscdrom], 0 + jz @f + DBG32 dbg_cdrom +@@: +end if mov esi, 0A000h+512 cmp dword [esi], 'EFI ' je @f @@ -967,7 +1007,6 @@ protmode_start: ; load INITRD from partition dec ecx shr ecx, 12 - xor edx, edx mov edi, dword [bootboot.initrd_ptr] @@: add edi, 4096 prot_readsector @@ -1044,7 +1083,6 @@ protmode_start: ;load root directory mov eax, dword [root_sec] - xor edx, edx mov edi, dword [bootboot.initrd_ptr] prot_readsector @@ -1072,15 +1110,12 @@ protmode_start: @@: mov ax, word [esi + fatdir.cl] ;sec = (cluster-2)*secPerCluster+data_sec sub eax, 2 - xor edx, edx mov ebx, dword [clu_sec] mul ebx add eax, dword [data_sec] mov edi, dword [bootboot.initrd_ptr] prot_readsector - mov dword [9000h], 0 - ;look for CONFIG and INITRD mov esi, edi mov ecx, 255 @@ -1115,7 +1150,6 @@ protmode_start: .nextcfg: push eax ;sec = (cluster-2)*secPerCluster+data_sec sub eax, 2 - xor edx, edx mov ebx, dword [clu_sec] mul ebx shl ebx, 9 @@ -1187,7 +1221,6 @@ protmode_start: .nextclu: push eax ;sec = (cluster-2)*secPerCluster+data_sec sub eax, 2 - xor edx, edx mov ebx, dword [clu_sec] mov word [lbapacket.count], bx mul ebx @@ -1894,9 +1927,18 @@ GDT_value: dw $-GDT_table dd GDT_table dd 0,0 align 16 +lbapacket: ;lba packet for BIOS +.size: dw 10h +.count: dw 8 +.addr: dd 0A000h +.sect0: dd 0 +.sect1: dd 0 +spc_packet: db 18h dup 0 entrypoint: dq 0 core_ptr: dd 0 core_len: dd 0 +reqwidth: dd 1024 +reqheight: dd 768 ebdaptr: dd 0 hw_stack: dd 0 bpb_sec: dd 0 ;ESP's first sector @@ -1906,17 +1948,11 @@ clu_sec: dd 0 ;sector per cluster gpt_ptr: dd 0 gpt_num: dd 0 gpt_ent: dd 0 -lbapacket: ;lba packet for BIOS -.size: dw 10h -.count: dw 8 -.addr: dd 0A000h -.sect0: dd 0 -.sect1: dd 0 -.flataddr: dd 0,0 -reqwidth: dd 1024 -reqheight: dd 768 +origcount: dw 0 bootdev: db 0 +readdev: db 0 hasinitrd: db 0 +iscdrom: db 0 fattype: db 0 vbememsize: dw 0 bkp: dd ' ' @@ -1926,6 +1962,7 @@ dbg_A20 db " * Enabling A20",10,13,0 dbg_mem db " * E820 Memory Map",10,13,0 dbg_systab db " * System tables",10,13,0 dbg_time db " * System time",10,13,0 +dbg_cdrom db " * Detected CDROM boot",10,13,0 dbg_env db " * Environment",10,13,0 dbg_initrd db " * Initrd loaded",10,13,0 dbg_gzinitrd db " * Gzip compressed initrd",10,13,0 @@ -1944,12 +1981,13 @@ nogzmem: db "Inflating: " noenmem: db "Not enough memory",0 noacpi: db "ACPI not found",0 nogpt: db "No boot partition",0 -nord: db "INITRD not found",0 +nord: db "Initrd not found",0 nolib: db "/sys not found in initrd",0 nocore: db "Kernel not found in initrd",0 badcore: db "Kernel is not a valid executable",0 novbe: db "VESA VBE error, no framebuffer",0 nogzip: db "Unable to uncompress",0 +notcdsect: db "Not 2048 sector aligned",0 cfgfile: db "sys/config",0,0,0 kernel: db "sys/core" db (128-($-kernel)) dup 0 diff --git a/x86_64-bios/mkboot.c b/x86_64-bios/mkboot.c index 072cc0c..b8fc1ba 100644 --- a/x86_64-bios/mkboot.c +++ b/x86_64-bios/mkboot.c @@ -25,7 +25,7 @@ * * This file is part of the BOOTBOOT Protocol package. * @brief Little tool to install boot.bin in MBR or VBR - * + * */ #include diff --git a/x86_64-efi/bootboot.c b/x86_64-efi/bootboot.c index baa0a84..d9dba3f 100644 --- a/x86_64-efi/bootboot.c +++ b/x86_64-efi/bootboot.c @@ -1071,6 +1071,6 @@ get_memory_map: "retq" : : "a"(entrypoint): "memory" ); } - return report(status,L"INITRD not found"); + return report(status,L"Initrd not found"); }