boot.asm 7.9 KB
Newer Older
bzt's avatar
bzt committed
1 2 3
;*
;* x86_64-bios/boot.asm
;*
bzt's avatar
bzt committed
4
;* Copyright (C) 2017 - 2020 bzt ([email protected])
bzt's avatar
bzt committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
;*
;* Permission is hereby granted, free of charge, to any person
;* obtaining a copy of this software and associated documentation
;* files (the "Software"), to deal in the Software without
;* restriction, including without limitation the rights to use, copy,
;* modify, merge, publish, distribute, sublicense, and/or sell copies
;* of the Software, and to permit persons to whom the Software is
;* furnished to do so, subject to the following conditions:
;*
;* The above copyright notice and this permission notice shall be
;* included in all copies or substantial portions of the Software.
;*
;* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
;* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
;* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
;* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
;* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
;* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
;* DEALINGS IN THE SOFTWARE.
;*
;* This file is part of the BOOTBOOT Protocol package.
bzt's avatar
bzt committed
27 28
;* @brief Stage1 loader, compatible with BIOS boot specification and
;* El Torito CD-ROM boot in "no emulation" mode
bzt's avatar
bzt committed
29 30 31 32 33 34 35
;*

;*********************************************************************
;*                             Macros                                *
;*********************************************************************

;LBA packet fields
36
lba_packet      equ     07E00h
bzt's avatar
bzt committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
virtual at lba_packet
lbapacket.size: dw      ?
lbapacket.count:dw      ?
lbapacket.addr0:dw      ?
lbapacket.addr1:dw      ?
lbapacket.sect0:dw      ?
lbapacket.sect1:dw      ?
lbapacket.sect2:dw      ?
lbapacket.sect3:dw      ?
end virtual

;memory locations
ldr.header      equ     800h        ;position of 2nd stage loader
ldr.executor    equ     804h        ;ptr to init code

;Writes a message on screen.
macro print msg
{
if ~ msg eq si
            push        si
            mov         si, msg
end if
            call        printfunc
if ~ msg eq si
            pop         si
end if
}

;*********************************************************************
;*                             code                                  *
;*********************************************************************

;-----------------ENTRY POINT called by BIOS--------------------
            ORG         0600h
            USE16

bootboot_record:
            jmp         short .skipid
            nop
            ;skip BPB area so that we can use this
77 78
            ;boot code on a FAT / exFAT volume if needed
            db          120-($-$$) dup 0
bzt's avatar
bzt committed
79
.skipid:    ;relocate our code to offset 0h:600h
bzt's avatar
bzt committed
80
            cli
bzt's avatar
bzt committed
81
            cld
bzt's avatar
bzt committed
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
            xor         ax, ax
            mov         ss, ax
            mov         sp, 600h
            push        ax
            pop         es
            push        cs
            pop         ds
            ;find our position in memory.
            call        .getaddr
.getaddr:   pop         si
            sub         si, .getaddr-bootboot_record
            mov         di, sp
            ;clear data area 500h-600h
            sub         di, 100h
            mov         cx, 80h
            repnz       stosw
            ;and copy ourselves to 600h
            mov         cx, 100h
            repnz       movsw
bzt's avatar
bzt committed
101 102 103
            ;have to clear ds, because cs is set to 7c0 when booted from El Torito
            push        es
            pop         ds
bzt's avatar
bzt committed
104 105 106 107 108
            jmp         0:.start

.start:     ;save boot drive code
            mov         byte [drive], dl
            ;check for lba presistance - floppy not supported any more
bzt's avatar
bzt committed
109
            ;we use USB sticks as removable media for a long time
bzt's avatar
bzt committed
110 111 112 113
            cmp         dl, byte 80h
            jl          .nolba
.notfloppy: mov         ah, byte 41h
            mov         bx, word 55AAh
bzt's avatar
bzt committed
114
            clc
bzt's avatar
bzt committed
115 116 117 118 119 120 121 122 123
            int         13h
            jc          .nolba
            cmp         bx, word 0AA55h
            jne         .nolba
            test        cl, byte 1
            jnz         .lbaok
.nolba:     mov         si, lbanotf
            jmp         diefunc
.lbaok:     ;try to load stage2 - it's a continous area on disk
bzt's avatar
bzt committed
124
            ;started at given sector with maximum size of 7000h bytes
125 126 127 128
            mov         di, lba_packet
            mov         cx, 8
            xor         ax, ax
            repnz       stosw
bzt's avatar
bzt committed
129 130
            mov         si, stage2_addr
            mov         di, lbapacket.sect0
bzt's avatar
bzt committed
131
            ;set up for hard-drive
bzt's avatar
bzt committed
132 133
            movsw
            movsw
134 135
            mov         byte [lbapacket.size], 16
            mov         byte [lbapacket.addr0+1], 08h   ;to address 800h
bzt's avatar
bzt committed
136 137
            mov         byte [lbapacket.count], 56
            mov         dl, byte [drive]
138 139 140 141
            ;if it's a CDROM with 2048 byte sectors
            cmp         dl, 0E0h
            jl          @f
            sub         di, 4
bzt's avatar
bzt committed
142 143 144 145 146 147 148
            ;lba=lba/4
            clc
            rcr         word [di+2], 1
            rcr         word [di], 1
            clc
            rcr         word [di+2], 1
            rcr         word [di], 1
149
            shr         word [lbapacket.count], 2
bzt's avatar
bzt committed
150 151 152 153
            ;load sectors
@@:         mov         ah, byte 42h
            mov         si, lba_packet
            int         13h
bzt's avatar
bzt committed
154 155

            ;do we have a 2nd stage loader?
156
.chk:       cmp         word [ldr.header], 0AA55h
bzt's avatar
bzt committed
157 158 159
            jne         .nostage2
            cmp         byte [ldr.header+3], 0E9h
            jne         .nostage2
160
            mov         dl, byte [drive]
bzt's avatar
bzt committed
161 162 163 164 165 166
            ;invoke stage2 real mode code
            mov         ax, [ldr.executor]
            add         ax, ldr.executor+3
            jmp         ax

.nostage2:  ;try to load stage2 from a RAID mirror
167 168 169 170 171 172 173 174 175
            mov         al, byte [drive]
            inc         al
            cmp         al, 87h
            jle         @f
            mov         al, 80h
@@:         mov         byte [drive], al
            inc         byte [cnt]
            cmp         byte [cnt], 8
            jl          .lbaok
bzt's avatar
bzt committed
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
.nostage2err:
            mov         si, stage2notf
            ;fall into the diefunc code

;*********************************************************************
;*                          functions                                *
;*********************************************************************
;writes the reason, waits for a key and reboots.
diefunc:
            print       panic
            call        printfunc
            mov         si, found
            call        printfunc
            sti
            xor         ax, ax
            int         16h
            mov         al, 0FEh
            out         64h, al
            jmp         far 0FFFFh:0    ;invoke BIOS POST routine

;ds:si zero terminated string to write
printfunc:
            lodsb
            or          al, al
            jz          .end
            mov         ah, byte 0Eh
            mov         bx, word 11
            int         10h
            jmp         printfunc
.end:       ret

;*********************************************************************
;*                          data area                                *
;*********************************************************************

211
panic:      db          "BOOTBOOT-PANIC: ",0
bzt's avatar
bzt committed
212 213
lbanotf:    db          "LBA support",0
stage2notf: db          "FS0:\BOOTBOOT\LOADER",0
214 215
found:      db          " not found",0
cnt:        db          0
bzt's avatar
bzt committed
216
drive:      db          0
bzt's avatar
bzt committed
217
            db          01B0h-($-$$) dup 0
bzt's avatar
bzt committed
218 219 220 221 222 223 224 225 226 227 228 229 230 231

;right before the partition table some data
stage2_addr:dd          0FFFFFFFFh,0    ;1B0h 2nd stage loader address
                                        ;this should be set by mkfs

diskid:     dd          0               ;1B8h WinNT expects it here
            dw          0

;1BEh first partition entry

            ;padding and magic
            db          01FEh-($-$$) dup 0
            db          55h,0AAh
bootboot_record_end: