| 1 | org 0x7c00 |
| 2 | bits 16 |
| 3 | |
| 4 | start: |
| 5 | jmp .skip_bpb ; Workaround for some BIOSes that require this stub |
| 6 | nop |
| 7 | |
| 8 | ; Some BIOSes will do a funny and decide to overwrite bytes of code in |
| 9 | ; the section where a FAT BPB would be, potentially overwriting |
| 10 | ; bootsector code. |
| 11 | ; Avoid that by filling the BPB area with dummy values. |
| 12 | ; Some of the values have to be set to certain values in order |
| 13 | ; to boot on even quirkier machines. |
| 14 | ; Source: https://github.com/freebsd/freebsd-src/blob/82a21151cf1d7a3e9e95b9edbbf74ac10f386d6a/stand/i386/boot2/boot1.S |
| 15 | .bpb: |
| 16 | times 3-($-$$) db 0 |
| 17 | .bpb_oem_id: db "LIMINE " |
| 18 | .bpb_sector_size: dw 512 |
| 19 | .bpb_sects_per_cluster: db 0 |
| 20 | .bpb_reserved_sects: dw 0 |
| 21 | .bpb_fat_count: db 0 |
| 22 | .bpb_root_dir_entries: dw 0 |
| 23 | .bpb_sector_count: dw 0 |
| 24 | .bpb_media_type: db 0 |
| 25 | .bpb_sects_per_fat: dw 0 |
| 26 | .bpb_sects_per_track: dw 18 |
| 27 | .bpb_heads_count: dw 2 |
| 28 | .bpb_hidden_sects: dd 0 |
| 29 | .bpb_sector_count_big: dd 0 |
| 30 | .bpb_drive_num: db 0 |
| 31 | .bpb_reserved: db 0 |
| 32 | .bpb_signature: db 0 |
| 33 | .bpb_volume_id: dd 0 |
| 34 | .bpb_volume_label: db "LIMINE " |
| 35 | .bpb_filesystem_type: times 8 db 0 |
| 36 | |
| 37 | .skip_bpb: |
| 38 | cli |
| 39 | cld |
| 40 | jmp 0x0000:.initialise_cs |
| 41 | .initialise_cs: |
| 42 | xor si, si |
| 43 | mov ds, si |
| 44 | mov es, si |
| 45 | mov ss, si |
| 46 | mov sp, 0x7c00 |
| 47 | sti |
| 48 | |
| 49 | ; Limine isn't made for floppy disks, these are dead anyways. |
| 50 | ; So if the value the BIOS passed is <0x80, just assume it has passed |
| 51 | ; an incorrect value. |
| 52 | cmp dl, 0x80 |
| 53 | jb err.0 |
| 54 | ; Values above 0x8f are dubious so we assume we weren't booted properly |
| 55 | ; for those either |
| 56 | cmp dl, 0x8f |
| 57 | ja err.1 |
| 58 | |
| 59 | .continue: |
| 60 | ; Make sure int 13h extensions are supported |
| 61 | mov ah, 0x41 |
| 62 | mov bx, 0x55aa |
| 63 | int 0x13 |
| 64 | jc err.2 |
| 65 | cmp bx, 0xaa55 |
| 66 | jne err.3 |
| 67 | |
| 68 | push 0x7000 |
| 69 | pop es |
| 70 | mov di, stage2_loc |
| 71 | mov eax, dword [di] |
| 72 | mov ebp, dword [di+4] |
| 73 | xor bx, bx |
| 74 | mov ecx, 32256 ; 32KiB minus boot sector size |
| 75 | call read_sectors |
| 76 | jc err.4 |
| 77 | |
| 78 | lgdt [gdt] |
| 79 | |
| 80 | cli |
| 81 | |
| 82 | push dword 0 |
| 83 | mov ebp, 0x10 |
| 84 | |
| 85 | mov eax, cr0 |
| 86 | bts ax, 0 |
| 87 | mov cr0, eax |
| 88 | |
| 89 | jmp 0x08:vector |
| 90 | |
| 91 | times 0xda-($-$$) db 0 |
| 92 | times 6 db 0 |
| 93 | |
| 94 | ; Includes |
| 95 | |
| 96 | %include 'disk.asm' |
| 97 | %include '../gdt.asm' |
| 98 | |
| 99 | err: |
| 100 | .4: |
| 101 | inc si |
| 102 | .3: |
| 103 | inc si |
| 104 | .2: |
| 105 | inc si |
| 106 | .1: |
| 107 | inc si |
| 108 | .0: |
| 109 | add si, '0' | (0x4f << 8) |
| 110 | |
| 111 | push 0xb800 |
| 112 | pop es |
| 113 | mov word [es:0], si |
| 114 | |
| 115 | sti |
| 116 | .h: hlt |
| 117 | jmp .h |
| 118 | |
| 119 | bits 32 |
| 120 | vector: |
| 121 | mov ds, ebp |
| 122 | mov es, ebp |
| 123 | mov fs, ebp |
| 124 | mov gs, ebp |
| 125 | mov ss, ebp |
| 126 | |
| 127 | and edx, 0xff |
| 128 | |
| 129 | push edx |
| 130 | |
| 131 | push stage2.size |
| 132 | push (stage2 - decompressor) + 0x70000 |
| 133 | |
| 134 | call 0x70000 |
| 135 | |
| 136 | times 0x1a4-($-$$) db 0 |
| 137 | stage2_loc: dq 0 |
| 138 | |
| 139 | times 0x1b8-($-$$) db 0 |
| 140 | times 510-($-$$) db 0 |
| 141 | dw 0xaa55 |
| 142 | |
| 143 | ; ********************* Stage 2 ********************* |
| 144 | |
| 145 | decompressor: |
| 146 | %strcat DECOMPRESSOR_PATH BUILDDIR, '/decompressor-build/decompressor.bin' |
| 147 | incbin DECOMPRESSOR_PATH |
| 148 | |
| 149 | align 16 |
| 150 | stage2: |
| 151 | %strcat STAGE2_PATH BUILDDIR, '/common-bios/stage2.bin.limlz' |
| 152 | incbin STAGE2_PATH |
| 153 | .size: equ $ - stage2 |