mirror of
https://gitlab.com/bztsrc/bootboot.git
synced 2023-02-13 20:54:32 -05:00
3099 lines
109 KiB
NASM
3099 lines
109 KiB
NASM
;*
|
|
;* x86_64-bios/bootboot.asm
|
|
;*
|
|
;* Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab)
|
|
;*
|
|
;* 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.
|
|
;* @brief Booting code for BIOS, MultiBoot, El Torito, Linux boot
|
|
;*
|
|
;* Stage2 loader, compatible with GRUB and BIOS boot specification
|
|
;* 1.0.1 (even expansion ROM), El Torito "no emulation" CDROM boot,
|
|
;* as well as Linux boot protocol.
|
|
;*
|
|
;* text segment occupied: 800-7C00, bss: 8000-x
|
|
;*
|
|
;* Memory map
|
|
;* 0h - 600h reserved for the system
|
|
;* 600h - 800h stage1 (MBR/VBR, boot.bin)
|
|
;* 800h - 6C00h stage2 (this)
|
|
;* 6C00h - 7C00h stack (7000h - 700Fh SMP trampoline code)
|
|
;* 8000h - 9000h bootboot structure
|
|
;* 9000h - A000h environment
|
|
;* A000h - B000h disk buffer / PML4
|
|
;* B000h - C000h PDPE, higher half core 4K slots
|
|
;* C000h - D000h PDE 4K
|
|
;* D000h - E000h PTE 4K
|
|
;* E000h - F000h PDPE, 4G physical RAM identity mapped 2M
|
|
;* F000h - 10000h PDE 2M
|
|
;* 10000h - 11000h PDE 2M
|
|
;* 11000h - 12000h PDE 2M
|
|
;* 12000h - 13000h PDE 2M
|
|
;* 13000h - 14000h PTE 4K
|
|
;* 14000h - 9F000h core stacks (1k per core)
|
|
;*
|
|
;* At first big enough free hole, initrd. Usually at 1Mbyte.
|
|
;*
|
|
;* WARNING: supports BOOTBOOT Protocol level 1 only (static mappings)
|
|
;*
|
|
|
|
BBDEBUG equ 1
|
|
|
|
;get Core boot parameter block
|
|
include "bootboot.inc"
|
|
|
|
;VBE filter (available, has additional info, color, graphic, linear fb)
|
|
VBE_MODEFLAGS equ 1+2+8+16+128
|
|
|
|
;*********************************************************************
|
|
;* Macros *
|
|
;*********************************************************************
|
|
|
|
;Writes a message on screen.
|
|
macro real_print msg
|
|
{
|
|
if ~ msg eq si
|
|
push si
|
|
mov si, msg
|
|
end if
|
|
call real_printfunc
|
|
if ~ msg eq si
|
|
pop si
|
|
end if
|
|
}
|
|
|
|
;protected and real mode are functions, because we have to switch beetween
|
|
macro real_protmode
|
|
{
|
|
USE16
|
|
call near real_protmodefunc
|
|
USE32
|
|
}
|
|
|
|
macro prot_realmode
|
|
{
|
|
USE32
|
|
call near prot_realmodefunc
|
|
USE16
|
|
}
|
|
|
|
;edx:eax sector, edi:pointer
|
|
macro prot_readsector
|
|
{
|
|
call near prot_readsectorfunc
|
|
}
|
|
|
|
macro prot_sleep delay
|
|
{
|
|
mov ecx, delay
|
|
call near prot_sleepfunc
|
|
}
|
|
|
|
macro DBG msg
|
|
{
|
|
if BBDEBUG eq 1
|
|
real_print msg
|
|
end if
|
|
}
|
|
|
|
macro DBG32 msg
|
|
{
|
|
if BBDEBUG eq 1
|
|
prot_realmode
|
|
real_print msg
|
|
real_protmode
|
|
end if
|
|
}
|
|
|
|
virtual at 0
|
|
bpb.jmp db 3 dup 0
|
|
bpb.oem db 8 dup 0
|
|
bpb.bps dw 0
|
|
bpb.spc db 0
|
|
bpb.rsc dw 0
|
|
bpb.nf db 0 ;16
|
|
bpb.nr dw 0
|
|
bpb.ts16 dw 0
|
|
bpb.media db 0
|
|
bpb.spf16 dw 0 ;22
|
|
bpb.spt dw 0
|
|
bpb.nh dw 0
|
|
bpb.hs dd 0
|
|
bpb.ts32 dd 0
|
|
bpb.spf32 dd 0 ;36
|
|
bpb.flg dd 0
|
|
bpb.rc dd 0 ;44
|
|
bpb.vol db 6 dup 0
|
|
bpb.fst db 8 dup 0 ;54
|
|
bpb.dmy db 20 dup 0
|
|
bpb.fst2 db 8 dup 0 ;84
|
|
end virtual
|
|
|
|
virtual at 0
|
|
fatdir.name db 8 dup 0
|
|
fatdir.ext db 3 dup 0
|
|
fatdir.attr db 9 dup 0
|
|
fatdir.ch dw 0
|
|
fatdir.attr2 dd 0
|
|
fatdir.cl dw 0
|
|
fatdir.size dd 0
|
|
end virtual
|
|
|
|
;*********************************************************************
|
|
;* header *
|
|
;*********************************************************************
|
|
;offs len desc
|
|
; 0 2 expansion ROM magic (AA55h)
|
|
; 2 1 size in blocks (40h)
|
|
; 3 1 magic E9h
|
|
; 4 2 real mode entry point (relative)
|
|
; 6 2 checksum
|
|
; 8 8 magic 'BOOTBOOT'
|
|
; 16 10 zeros, at least one and a padding
|
|
; 26 2 pnp ptr, must be zero
|
|
; 28 4 flags, must be zero
|
|
; 32 32 MultiBoot header with protected mode entry point
|
|
; 64 x free to use
|
|
;497 127 Linux x86 boot protocol header
|
|
;any format can follow.
|
|
|
|
USE16
|
|
ORG 800h
|
|
;BOOTBOOT stage2 header (64 bytes)
|
|
loader: db 55h,0AAh ;ROM magic
|
|
db (loader_end-loader)/512 ;size in 512 blocks
|
|
.executor: jmp near realmode_start ;entry point
|
|
.checksum: dw 0 ;checksum
|
|
.name: db "BOOTBOOT"
|
|
dw 0
|
|
dd 0, 0
|
|
.pnpptr: dw 0
|
|
.flags: dd 0
|
|
MB_MAGIC equ 01BADB002h
|
|
MB_FLAGS equ 010001h
|
|
align 8
|
|
.mb_header: dd MB_MAGIC ;magic
|
|
dd MB_FLAGS ;flags
|
|
dd -(MB_MAGIC+MB_FLAGS) ;checksum (0-magic-flags)
|
|
dd .mb_header ;our location (GRUB should load us here)
|
|
dd 0800h ;the same... load start
|
|
dd 07C00h ;load end
|
|
dd 0h ;no bss
|
|
dd multiboot_start ;entry point
|
|
|
|
;no segments or sections, code comes right after the header
|
|
|
|
;*********************************************************************
|
|
;* code *
|
|
;*********************************************************************
|
|
|
|
;----------------Multiboot stub-----------------
|
|
USE32
|
|
multiboot_start:
|
|
cli
|
|
cld
|
|
;clear drive code, initrd ptr and environment
|
|
xor edx, edx
|
|
mov edi, 9000h
|
|
mov dword [edi], edx
|
|
mov dword [bootboot.initrd_ptr], edx
|
|
mov dword [bootboot.initrd_size], edx
|
|
;no GRUB environment available?
|
|
cmp eax, 2BADB002h
|
|
jne @f
|
|
;save drive code for boot device
|
|
mov dl, byte [ebx+12]
|
|
;is there a module? mod_count!=0
|
|
cmp dword [ebx+20], 0
|
|
jz @f
|
|
;mod_addr!=0
|
|
mov eax, dword [ebx+24]
|
|
or eax, eax
|
|
jz @f
|
|
;mods[0].end
|
|
mov ecx, dword [eax+4]
|
|
sub ecx, dword [eax]
|
|
mov dword [bootboot.initrd_size], ecx
|
|
;mods[0].start
|
|
mov ecx, dword [eax]
|
|
mov dword [bootboot.initrd_ptr], ecx
|
|
inc byte [hasinitrd]
|
|
;mod_count>1?
|
|
cmp dword [ebx+20], 1
|
|
jbe @f
|
|
;mods[1], copy environment (4k)
|
|
mov esi, dword [eax+16]
|
|
mov ecx, 1024
|
|
repnz movsd
|
|
inc byte [hasconfig]
|
|
@@: lgdt [GDT_value]
|
|
mov ax, DATA_BOOT ;clear shadow segment registers
|
|
mov ds, ax
|
|
mov es, ax
|
|
mov ss, ax
|
|
xor esp, esp ;GRUB leaves the upper 16 bits non-zero, we must clear it
|
|
jmp CODE_BOOT:.real ;load 16 bit mode segment into cs
|
|
USE16
|
|
.real: mov eax, CR0
|
|
and eax, 07FFFFFFEh ;switching back to real mode
|
|
mov CR0, eax
|
|
xor ax, ax
|
|
mov ds, ax ;load segment registers DS and CS
|
|
jmp 0:@f
|
|
@@: lidt [idt16] ;restore IDT as newer GRUBs mess it up
|
|
;fallthrough realmode_start
|
|
|
|
;-----------realmode-protmode stub-------------
|
|
realmode_start:
|
|
cli
|
|
cld
|
|
mov sp, 7C00h
|
|
xor ax, ax
|
|
mov es, ax
|
|
mov ss, ax
|
|
;relocate ourself from ROM to RAM if necessary
|
|
call .getaddr
|
|
.getaddr: pop si
|
|
mov ax, cs
|
|
or ax, ax
|
|
jnz .reloc
|
|
cmp si, .getaddr
|
|
je .noreloc
|
|
.reloc: mov ds, ax
|
|
mov di, loader
|
|
sub si, .getaddr-loader
|
|
mov cx, (loader_end-loader)/2
|
|
repnz movsw
|
|
xor ax, ax
|
|
mov ds, ax
|
|
jmp 0:.clrdl
|
|
.noreloc: or dl, dl
|
|
jnz @f
|
|
.clrdl: mov dl, 80h
|
|
@@: mov byte [bootdev], dl
|
|
;get CDROM drive code
|
|
mov ax, word 4B01h
|
|
mov si, entrypoint ; bss area
|
|
mov byte [si + 2], 0E0h
|
|
push si
|
|
int 13h
|
|
pop si
|
|
jc @f
|
|
mov al, byte [si + 2]
|
|
mov byte [cdromdev], al
|
|
@@:
|
|
;-----initialize serial port COM1,115200,8N1------
|
|
mov ax, 0401h
|
|
xor bx, bx
|
|
mov cx, 030Bh
|
|
xor dx, dx
|
|
int 14h
|
|
; if there's no serial, but BIOS incorrectly sets the IO port for it
|
|
mov dx, word [400h]
|
|
or dx, dx
|
|
jz @f
|
|
add dx, 5
|
|
in al, dx
|
|
cmp al, 0FFh
|
|
jne @f
|
|
mov word [400h], 0
|
|
@@: real_print starting
|
|
|
|
; flush PS/2 keyboard
|
|
in al, 060h ; read key
|
|
in al, 061h ; ack
|
|
out 061h, al
|
|
|
|
DBG dbg_cpu
|
|
|
|
;-----check CPU-----
|
|
;at least 286?
|
|
pushf
|
|
pushf
|
|
pop dx
|
|
xor dh,40h
|
|
push dx
|
|
popf
|
|
pushf
|
|
pop bx
|
|
popf
|
|
cmp dx, bx
|
|
jne .cpuerror
|
|
mov ebp, 200000h
|
|
;check for 386
|
|
;look for cpuid instruction
|
|
pushfd
|
|
pop eax
|
|
mov ebx, eax
|
|
xor eax, ebp
|
|
and ebx, ebp
|
|
push eax
|
|
popfd
|
|
pushfd
|
|
pop eax
|
|
and eax, ebp
|
|
xor eax, ebx
|
|
shr eax, 21
|
|
and al, 1
|
|
jz .cpuerror
|
|
;ok, now we can get cpu feature flags
|
|
mov eax, 1
|
|
cpuid
|
|
shr al, 4
|
|
shr ebx, 24
|
|
mov word [bootboot.bspid], bx
|
|
;look for minimum family
|
|
cmp ax, 0600h
|
|
jb .cpuerror
|
|
;look for minimum feature flags
|
|
;do we have PAE?
|
|
bt edx, 6
|
|
jnc .cpuerror
|
|
;what about MSR?
|
|
bt edx, 5
|
|
jnc .cpuerror
|
|
;do we have RDTSC instruction?
|
|
bt edx, 4
|
|
jnc .cpuerror
|
|
;and can we use long mode (LME)?
|
|
mov eax, 80000000h
|
|
mov ebp, eax
|
|
inc ebp
|
|
cpuid
|
|
cmp eax, ebp
|
|
jb .cpuerror
|
|
mov eax, ebp
|
|
cpuid
|
|
;long mode
|
|
bt edx, 29
|
|
jc cpuok
|
|
.cpuerror: mov si, noarch
|
|
jmp real_diefunc
|
|
;okay, we can do 64 bit!
|
|
|
|
;--- Linux x86 boot protocol header ---
|
|
db 01F1h-($-$$) dup 090h
|
|
hdr:
|
|
setup_sects: db (loader_end-loader-511)/512
|
|
root_flags: dw 0
|
|
syssize: dd (loader_end-loader)/16
|
|
ram_size: dw 0
|
|
vid_mode: dw 0
|
|
root_dev: dw 0
|
|
boot_flag: dw 0AA55h
|
|
db 0EBh ; short jmp
|
|
db start_of_setup-@f ; no space to jump to realmode_start directly
|
|
@@: db "HdrS"
|
|
dw 020eh
|
|
realmode_swtch: dd 0
|
|
start_sys_seg: dw 0
|
|
dw 0 ; we don't have Linux kernel version...
|
|
type_of_loader: db 0FFh
|
|
loadflags: db 0
|
|
setup_move_size: dw 08000h
|
|
code32_start: dd 0 ; we dont' use this either...
|
|
ramdisk_image: dd 0
|
|
ramdisk_size: dd 0
|
|
bootsect_kludge: dd 0
|
|
heap_end_ptr: dd loader_end+1024-512 ; we don't care, we set our stack directly
|
|
ext_loader_ver: db 0
|
|
ext_loader_type: db 0
|
|
cmd_line_ptr: dd 0
|
|
initrd_addr_max: dd 07fffffffh
|
|
kernel_alignment: dd 16
|
|
relocatable_kernel: db 0
|
|
min_alignment: db 4
|
|
xloadflags: dw 0
|
|
cmdline_size: dd 0
|
|
hardware_subarch: dd 0
|
|
hardware_subarch_data: dq 0
|
|
payload_offset: dd 0
|
|
payload_length: dd 0
|
|
setup_data: dq 0
|
|
pref_address: dq 90000h ; qemu does not handle anything else
|
|
init_size: dd loader_end-loader
|
|
handover_offset: dd 0
|
|
acpi_rsdp_addr: dq 0
|
|
start_of_setup:
|
|
; fix: qemu forces address and set CS to 0x9020, but we must jump to segment 0x9000.
|
|
jmp 9000h:realmode_start-loader
|
|
; --- end of Linux boot protocol header ---
|
|
|
|
cpuok: DBG dbg_A20
|
|
|
|
;-----enable A20-----
|
|
;no problem even if a20 is already turned on.
|
|
mov ax, 2401h ;BIOS enable A20 function
|
|
int 15h
|
|
;see if it worked
|
|
call a20chk
|
|
jz a20ok
|
|
;keyboard nightmare
|
|
call a20wait
|
|
mov al, 0ADh
|
|
out 64h, al
|
|
call a20wait
|
|
mov al, 0D0h
|
|
out 64h, al
|
|
call a20wait2
|
|
in al, 60h
|
|
push ax
|
|
call a20wait
|
|
mov al, 0D1h
|
|
out 64h, al
|
|
call a20wait
|
|
pop ax
|
|
or al, 2
|
|
out 60h, al
|
|
call a20wait
|
|
mov al, 0AEh
|
|
out 64h, al
|
|
call a20wait
|
|
call a20chk
|
|
jz a20ok
|
|
;fast enable method
|
|
in al, 92h
|
|
test al, 2
|
|
jnz a20ok
|
|
or al, 2
|
|
and al, 0FEh
|
|
out 92h, al
|
|
jmp a20ok
|
|
|
|
a20chk: push es
|
|
xor ax, ax
|
|
dec ax
|
|
mov es, ax
|
|
mov ah, byte [es:510h]
|
|
mov byte [ds:500h], 0
|
|
mov byte [es:510h], al
|
|
mov al, byte [ds:500h]
|
|
mov byte [es:510h], ah
|
|
pop es
|
|
or al, al
|
|
ret
|
|
a20wait: in al, 64h
|
|
test al, 2
|
|
jnz a20wait
|
|
ret
|
|
a20wait2: in al, 64h
|
|
test al, 1
|
|
jz a20wait2
|
|
ret
|
|
a20ok:
|
|
; calibrate RDTSC
|
|
rdtsc
|
|
mov dword [ncycles], eax
|
|
mov dword [ncycles+4], edx
|
|
; wait 200 usec
|
|
xor cx, cx
|
|
mov dx, 200
|
|
mov ah, 086h
|
|
int 15h
|
|
rdtsc
|
|
sub eax, dword [ncycles]
|
|
sbb edx, dword [ncycles+4]
|
|
mov dword [ncycles], eax
|
|
mov dword [ncycles+4], edx
|
|
|
|
; wait for a key press for half a sec, if pressed use backup initrd
|
|
mov word [origcount], 0
|
|
sti
|
|
.waitkey: mov ax, word 0100h
|
|
or al, al ; make sure ZF is clear
|
|
int 16h
|
|
jz @f
|
|
or al, al
|
|
jz @f
|
|
; this blocks, so only call it if we are sure there's a keystroke waiting
|
|
xor ah, ah
|
|
int 16h
|
|
mov eax, ' BAK'
|
|
mov dword [bkp], eax
|
|
real_print backup
|
|
jmp .waitend
|
|
@@: ; wait 10 millisec
|
|
xor cx, cx
|
|
mov dx, 10000
|
|
mov ah, 086h
|
|
int 15h
|
|
; repeat loop 50 times
|
|
inc word [origcount]
|
|
cmp word [origcount], 50
|
|
jl .waitkey
|
|
.waitend: cli
|
|
|
|
;-----detect memory map-----
|
|
getmemmap:
|
|
DBG dbg_mem
|
|
|
|
xor eax, eax
|
|
mov edi, bootboot.acpi_ptr
|
|
mov ecx, 16
|
|
repnz stosd
|
|
cmp byte [hasconfig], 0
|
|
jnz @f
|
|
mov dword [9000h], eax
|
|
@@: cmp byte [hasinitrd], 0
|
|
jnz @f
|
|
mov dword [bootboot.initrd_ptr], eax
|
|
mov dword [bootboot.initrd_size], eax
|
|
@@: mov dword [bootboot.initrd_ptr+4], eax
|
|
mov dword [bootboot.initrd_size+4], eax
|
|
mov eax, bootboot_MAGIC
|
|
mov dword [bootboot.magic], eax
|
|
mov dword [bootboot.size], 128
|
|
mov dword [bootboot.protocol], PROTOCOL_STATIC or LOADER_BIOS
|
|
mov di, bootboot.fb_ptr
|
|
mov cx, 800h-28h
|
|
xor ax, ax
|
|
repnz stosw
|
|
mov di, bootboot.mmap
|
|
xor ebx, ebx
|
|
clc
|
|
.nextmap: cmp word [bootboot.size], 4096
|
|
jae .nomoremap
|
|
mov edx, 'PAMS'
|
|
xor ecx, ecx
|
|
mov cl, 20
|
|
xor eax, eax
|
|
mov ax, 0E820h
|
|
int 15h
|
|
jc .nomoremap
|
|
cmp eax, 'PAMS'
|
|
jne .nomoremap
|
|
;is this the first memory hole? If so, mark
|
|
;ourself as reserved memory
|
|
cmp dword [di+4], 0
|
|
jnz .notfirst
|
|
cmp dword [di], 0
|
|
jnz .notfirst
|
|
; "allocate" memory for loader
|
|
mov eax, 14000h
|
|
add dword [di], eax
|
|
sub dword [di+8], eax
|
|
;convert E820 memory type to BOOTBOOT memory type
|
|
.notfirst: mov al, byte [di+16]
|
|
cmp al, 1
|
|
je .noov
|
|
cmp al, 4
|
|
je .isacpi
|
|
cmp al, 3
|
|
jne @f
|
|
.isacpi: mov al, MMAP_ACPI
|
|
jmp .noov
|
|
; everything else reserved
|
|
@@: mov al, MMAP_USED
|
|
.noov: ;copy memory type to size's least significant byte
|
|
mov byte [di+8], al
|
|
xor ecx, ecx
|
|
;is it ACPI area?
|
|
cmp al, MMAP_ACPI
|
|
jne .notacpi
|
|
mov dword [bootboot.acpi_ptr], edi
|
|
jmp .entryok
|
|
;is it free slot?
|
|
.notacpi: cmp al, MMAP_FREE
|
|
jne .notmax
|
|
.freemem: ;do we have a ramdisk area?
|
|
cmp dword [bootboot.initrd_ptr], 0
|
|
jnz .entryok
|
|
;is it big enough for the compressed and the inflated ramdisk?
|
|
mov ebp, (INITRD_MAXSIZE+2)*1024*1024
|
|
shr ebp, 20
|
|
shl ebp, 20
|
|
;is this free memory hole big enough? (first fit)
|
|
.sizechk: mov eax, dword [di+8] ;load size
|
|
xor al, al
|
|
mov edx, dword [di+12]
|
|
and edx, 000FFFFFFh
|
|
or edx, edx
|
|
jnz .bigenough
|
|
cmp eax, ebp
|
|
jb .entryok
|
|
.bigenough: mov eax, dword [di]
|
|
;save ramdisk pointer
|
|
mov dword [bootboot.initrd_ptr], eax
|
|
.entryok: ;get limit of memory
|
|
mov eax, dword [di+8] ;load size
|
|
and al, 0F0h ;clear lower tetrad for type
|
|
mov edx, dword [di+12]
|
|
add eax, dword [di] ;add base
|
|
adc edx, dword [di+4]
|
|
and edx, 000FFFFFFh
|
|
.notmax: add dword [bootboot.size], 16
|
|
;bubble up entry if necessary
|
|
push si
|
|
push di
|
|
.bubbleup: mov si, di
|
|
cmp di, bootboot.mmap
|
|
jbe .swapdone
|
|
sub di, 16
|
|
;order by base asc
|
|
mov eax, dword [si+4]
|
|
cmp eax, dword [di+4]
|
|
jb .swapmodes
|
|
jne .swapdone
|
|
mov eax, dword [si]
|
|
cmp eax, dword [di]
|
|
jae .swapdone
|
|
.swapmodes: push di
|
|
mov cx, 16/2
|
|
@@: mov dx, word [di]
|
|
lodsw
|
|
stosw
|
|
mov word [si-2], dx
|
|
dec cx
|
|
jnz @b
|
|
pop di
|
|
jmp .bubbleup
|
|
.swapdone: pop di
|
|
pop si
|
|
add di, 16
|
|
cmp di, bootboot.mmap+4096
|
|
jae .nomoremap
|
|
.skip: or ebx, ebx
|
|
jnz .nextmap
|
|
.nomoremap: cmp dword [bootboot.size], 128
|
|
jne .E820ok
|
|
.noE820: mov si, memerr
|
|
jmp real_diefunc
|
|
|
|
.E820ok: ;check if we have memory for the ramdisk
|
|
xor ecx, ecx
|
|
cmp dword [bootboot.initrd_ptr], ecx
|
|
jnz .enoughmem
|
|
.nomem: mov si, noenmem
|
|
jmp real_diefunc
|
|
.enoughmem:
|
|
|
|
;-----detect system structures-----
|
|
DBG dbg_systab
|
|
|
|
;do we need that scanning shit?
|
|
mov eax, dword [bootboot.acpi_ptr]
|
|
or eax, eax
|
|
jz @f
|
|
shr eax, 4
|
|
mov es, ax
|
|
;no if E820 map was correct
|
|
cmp dword [es:0], 'XSDT'
|
|
je .detsmbi
|
|
cmp dword [es:0], 'RSDT'
|
|
je .detsmbi
|
|
@@: inc dx
|
|
;get starting address min(EBDA,E0000)
|
|
mov ah,0C1h
|
|
stc
|
|
int 15h
|
|
mov bx, es
|
|
jnc @f
|
|
mov ax, [ebdaptr]
|
|
@@: cmp ax, 0E000h
|
|
jb .acpinext
|
|
mov ax, 0E000h
|
|
;detect ACPI ptr
|
|
.acpinext: mov es, ax
|
|
cmp dword [es:0], 'RSD '
|
|
jne .acpinotf
|
|
cmp dword [es:4], 'PTR '
|
|
jne .acpinotf
|
|
;ptr found
|
|
; do we have XSDT?
|
|
cmp dword [es:28], 0
|
|
jne .acpi2
|
|
cmp dword [es:24], 0
|
|
je .acpi1
|
|
.acpi2: mov eax, dword [es:24]
|
|
mov dword [bootboot.acpi_ptr], eax
|
|
mov edx, dword [es:28]
|
|
mov dword [bootboot.acpi_ptr+4], edx
|
|
jmp .chkacpi
|
|
; no, fallback to RSDT
|
|
.acpi1: mov eax, dword [es:16]
|
|
@@: mov dword [bootboot.acpi_ptr], eax
|
|
xor edx, edx
|
|
jmp .chkacpi
|
|
.acpinotf: xor eax, eax
|
|
mov ax, es
|
|
inc ax
|
|
cmp ax, 0A000h
|
|
jne @f
|
|
add ax, 03000h
|
|
@@: ;end of 1Mb?
|
|
or ax, ax
|
|
jnz .acpinext
|
|
mov si, noacpi
|
|
jmp real_diefunc
|
|
.chkacpi: ; check if memory is marked as ACPI in the memory map
|
|
mov esi, bootboot.mmap
|
|
mov edi, bootboot.magic
|
|
add edi, dword [bootboot.size]
|
|
.nextmm: cmp edx, dword [si+4]
|
|
jne .skipmm
|
|
mov ebx, dword [si]
|
|
cmp eax, ebx
|
|
jl .skipmm
|
|
add ebx, dword [si+8]
|
|
and bl, 0F0h
|
|
cmp eax, ebx
|
|
jge .skipmm
|
|
mov al, byte [si+8]
|
|
and al, 0F0h
|
|
or al, MMAP_ACPI
|
|
mov byte [si+8], al
|
|
jmp .detsmbi
|
|
.skipmm: add si, 16
|
|
cmp si, di
|
|
jl .nextmm
|
|
|
|
;detect SMBios tables
|
|
.detsmbi: xor eax, eax
|
|
mov ax, 0E000h
|
|
xor dx, dx
|
|
.smbnext: mov es, ax
|
|
push ax
|
|
cmp dword [es:0], '_SM_'
|
|
je .smbfound
|
|
cmp dword [es:0], '_MP_'
|
|
jne .smbnotf
|
|
shl eax, 4
|
|
mov dword [bootboot.mp_ptr], eax
|
|
bts dx, 2
|
|
jmp .smbnotf
|
|
.smbfound: shl eax, 4
|
|
mov dword [bootboot.smbi_ptr], eax
|
|
bts dx, 1
|
|
.smbnotf: pop ax
|
|
bt ax, 0
|
|
mov bx, ax
|
|
and bx, 03h
|
|
inc ax
|
|
;end of 1Mb?
|
|
or ax, ax
|
|
jnz .smbnext
|
|
;restore ruined es
|
|
.detend: push ds
|
|
pop es
|
|
|
|
DBG dbg_time
|
|
|
|
; ------- BIOS date and time -------
|
|
mov ah, 4
|
|
int 1Ah
|
|
jc .nobtime
|
|
;ch century
|
|
;cl year
|
|
xchg ch, cl
|
|
mov word [bootboot.datetime], cx
|
|
;dh month
|
|
;dl day
|
|
xchg dh, dl
|
|
mov word [bootboot.datetime+2], dx
|
|
mov ah, 2
|
|
int 1Ah
|
|
jc .nobtime
|
|
;ch hour
|
|
;cl min
|
|
xchg ch, cl
|
|
mov word [bootboot.datetime+4], cx
|
|
;dh sec
|
|
;dl daylight saving on/off
|
|
xchg dh, dl
|
|
mov word [bootboot.datetime+6], dx
|
|
.nobtime:
|
|
|
|
;---- enable protmode ----
|
|
cli
|
|
cld
|
|
lgdt [GDT_value]
|
|
mov eax, cr0
|
|
or al, 1
|
|
mov cr0, eax
|
|
jmp CODE_PROT:protmode_start
|
|
|
|
;---- enable protmode on APs ----
|
|
ap_trampoline:
|
|
;--this code will be relocated to the SIPI address --
|
|
cli
|
|
cld
|
|
jmp 0:ap_start
|
|
;--relocation end--
|
|
ap_start: xor ax, ax
|
|
mov ds, ax
|
|
lgdt [GDT_value]
|
|
mov eax, cr0
|
|
or al, 1
|
|
mov cr0, eax
|
|
jmp CODE_PROT:ap_prot
|
|
USE32
|
|
ap_prot: mov ax, DATA_PROT
|
|
mov ds, ax
|
|
mov es, ax
|
|
mov fs, ax
|
|
mov gs, ax
|
|
mov ss, ax
|
|
; enable Local APIC
|
|
mov esi, dword [lapic_ptr]
|
|
mov eax, dword [esi + 0F0h]
|
|
or ah, 1
|
|
mov dword [esi + 0F0h], eax
|
|
mov ecx, 1Bh ; enable APIC MSR
|
|
rdmsr
|
|
bt eax, 1
|
|
wrmsr
|
|
lock inc word [ap_done]
|
|
; spinlock until BSP finishes
|
|
@@: pause
|
|
cmp byte [bsp_done], 0
|
|
jz @b
|
|
jmp longmode_init
|
|
|
|
;writes the reason, waits for a key and reboots.
|
|
prot_diefunc:
|
|
prot_realmode
|
|
USE16
|
|
real_diefunc:
|
|
xor ax, ax
|
|
mov ds, ax
|
|
push si
|
|
real_print loader.name
|
|
real_print panic
|
|
pop si
|
|
call real_printfunc
|
|
mov si, crlf
|
|
call real_printfunc
|
|
call real_getchar
|
|
mov al, 0FEh
|
|
out 64h, al
|
|
jmp far 0FFFFh:0 ;invoke BIOS POST routine
|
|
|
|
; get a character from keyboard or from serial line
|
|
real_getchar:
|
|
pushf
|
|
sti
|
|
push si
|
|
push di
|
|
.chkser: cmp word [400h], 0
|
|
jz @f
|
|
mov ah, byte 03h
|
|
xor dx, dx
|
|
int 14h
|
|
bt ax, 8
|
|
jnc @f
|
|
mov ah, byte 02h
|
|
xor dx, dx
|
|
int 14h
|
|
jmp .gotch
|
|
@@: mov ah, byte 01h
|
|
int 16h
|
|
jz .chkser
|
|
xor ah, ah
|
|
int 16h
|
|
.gotch: pop di
|
|
pop si
|
|
popf
|
|
xor ah, ah
|
|
ret
|
|
|
|
;ds:si zero terminated string to write
|
|
real_printfunc:
|
|
lodsb
|
|
or al, al
|
|
jz .end
|
|
;out 0e9h, al
|
|
push si
|
|
push ax
|
|
mov ah, byte 0Eh
|
|
mov bx, word 11
|
|
int 10h
|
|
pop ax
|
|
cmp word [400h], 0
|
|
jz @f
|
|
mov ah, byte 01h
|
|
xor dx, dx
|
|
int 14h
|
|
;if BIOS timed out, clear the IO address
|
|
;so that further calls won't try sending
|
|
and ah, 80h
|
|
jz @f
|
|
mov word[400h], 0
|
|
@@: pop si
|
|
jmp real_printfunc
|
|
.end: ret
|
|
|
|
real_protmodefunc:
|
|
cli
|
|
;get return address
|
|
xor ebp, ebp
|
|
pop bp
|
|
mov dword [hw_stack], esp
|
|
lgdt [GDT_value]
|
|
mov eax, cr0 ;enable protected mode
|
|
or al, 1
|
|
mov cr0, eax
|
|
jmp CODE_PROT:.init
|
|
|
|
USE32
|
|
.init: mov ax, DATA_PROT
|
|
mov ds, ax
|
|
mov es, ax
|
|
mov fs, ax
|
|
mov gs, ax
|
|
mov ss, ax
|
|
mov esp, dword [hw_stack]
|
|
jmp ebp
|
|
|
|
prot_realmodefunc:
|
|
cli
|
|
;get return address
|
|
pop ebp
|
|
;save stack pointer
|
|
mov dword [hw_stack], esp
|
|
jmp CODE_BOOT:.back ;load 16 bit mode segment into cs
|
|
USE16
|
|
.back: mov eax, CR0
|
|
and al, 0FEh ;switching back to real mode
|
|
mov CR0, eax
|
|
xor ax, ax
|
|
mov ds, ax ;load registers 2nd turn
|
|
mov es, ax
|
|
mov ss, ax
|
|
jmp 0:.back2
|
|
.back2: mov sp, word [hw_stack]
|
|
sti
|
|
jmp bp
|
|
|
|
USE32
|
|
prot_readsectorfunc:
|
|
push eax
|
|
push ecx
|
|
push esi
|
|
push edi
|
|
;load 8 sectors (1 page) or more in low memory
|
|
mov dword [lbapacket.sect0], eax
|
|
prot_realmode
|
|
;try all drives from bootdev-87 to support RAID mirror
|
|
mov dl, byte [bootdev]
|
|
mov byte [readdev], dl
|
|
mov byte [cntdev], 0
|
|
mov byte [iscdrom], 0
|
|
.again: mov ax, word [lbapacket.count]
|
|
mov word [origcount], ax
|
|
mov dl, byte [readdev]
|
|
cmp dl, byte [cdromdev]
|
|
jl @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 or 2048 (%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 ah, byte 42h
|
|
mov esi, lbapacket
|
|
clc
|
|
int 13h
|
|
jnc .rdok
|
|
;we do not expect this to fail, but if so, load sector from another
|
|
;drive assuming we have a RAID mirror. This will fail for non-RAIDs
|
|
mov al, byte [readdev]
|
|
inc al
|
|
cmp al, 87h
|
|
jle @f
|
|
mov al, 80h
|
|
@@: mov byte [readdev], al
|
|
inc byte [cntdev]
|
|
cmp byte [cntdev], 8
|
|
jle .again
|
|
.rdok: xor ebx, ebx
|
|
mov bl, ah
|
|
real_protmode
|
|
pop edi
|
|
or edi, edi
|
|
jz @f
|
|
push edi
|
|
;and copy to addr where it wanted to be (maybe in high memory)
|
|
mov esi, dword [lbapacket.addr]
|
|
xor ecx, ecx
|
|
mov cx, word [origcount]
|
|
shl ecx, 7
|
|
repnz movsd
|
|
pop edi
|
|
@@: pop esi
|
|
pop ecx
|
|
pop eax
|
|
ret
|
|
|
|
prot_hex2bin:
|
|
xor eax, eax
|
|
xor ebx, ebx
|
|
@@: mov bl, byte [esi]
|
|
cmp bl, '0'
|
|
jb @f
|
|
cmp bl, '9'
|
|
jbe .num
|
|
cmp bl, 'A'
|
|
jb @f
|
|
cmp bl, 'F'
|
|
ja @f
|
|
sub bl, 7
|
|
.num: sub bl, '0'
|
|
shl eax, 4
|
|
add eax, ebx
|
|
inc esi
|
|
dec cx
|
|
jnz @b
|
|
@@: ret
|
|
|
|
prot_dec2bin:
|
|
xor eax, eax
|
|
xor ebx, ebx
|
|
xor edx, edx
|
|
mov ecx, 10
|
|
@@: mov bl, byte [esi]
|
|
cmp bl, '0'
|
|
jb @f
|
|
cmp bl, '9'
|
|
ja @f
|
|
mul ecx
|
|
sub bl, '0'
|
|
add eax, ebx
|
|
inc esi
|
|
jmp @b
|
|
@@: ret
|
|
|
|
;IN: eax=str ptr, ecx=length OUT: eax=num
|
|
prot_oct2bin:
|
|
push ebx
|
|
push edx
|
|
mov ebx, eax
|
|
xor eax, eax
|
|
xor edx, edx
|
|
@@: shl eax, 3
|
|
mov dl, byte[ebx]
|
|
sub dl, '0'
|
|
add eax, edx
|
|
inc ebx
|
|
dec ecx
|
|
jnz @b
|
|
pop edx
|
|
pop ebx
|
|
ret
|
|
|
|
; IN: ecx delay time in 200 usec units
|
|
prot_sleepfunc:
|
|
push edx
|
|
rdtsc
|
|
mov dword [gpt_ptr], eax
|
|
mov dword [gpt_ptr+4], edx
|
|
mov eax, dword [ncycles]
|
|
mov edx, dword [ncycles+4]
|
|
mul ecx
|
|
add dword [gpt_ptr], eax
|
|
adc dword [gpt_ptr+4], edx
|
|
@@: pause
|
|
rdtsc
|
|
cmp dword [gpt_ptr+4], edx
|
|
jl @b
|
|
cmp dword [gpt_ptr], eax
|
|
jl @b
|
|
pop edx
|
|
ret
|
|
|
|
; IN: al, character to send
|
|
uart_send: mov ah, al
|
|
mov dx, word [400h] ;3fdh
|
|
add dx, 5
|
|
@@: pause
|
|
in al, dx
|
|
and al, 20h
|
|
jz @b
|
|
sub dx, 5
|
|
mov al, ah
|
|
out dx, al
|
|
ret
|
|
|
|
; IN: edi pointer to store the received char
|
|
uart_getc: mov dx, word [400h] ;3fdh
|
|
add dx, 5
|
|
@@: pause
|
|
in al, dx
|
|
and al, 1
|
|
jz @b
|
|
sub dl, 5
|
|
in al, dx
|
|
stosb
|
|
ret
|
|
|
|
protmode_start:
|
|
mov ax, DATA_PROT
|
|
mov ds, ax
|
|
mov es, ax
|
|
mov fs, ax
|
|
mov gs, ax
|
|
mov ss, ax
|
|
mov esp, 7C00h
|
|
|
|
; ------- Locate initrd --------
|
|
cmp byte [hasinitrd], 0
|
|
jnz .initrdrom
|
|
mov esi, 0C8000h
|
|
.nextrom: cmp word [esi], 0AA55h
|
|
jne @f
|
|
cmp dword [esi+8], 'INIT'
|
|
jne @f
|
|
cmp word [esi+12], 'RD'
|
|
jne @f
|
|
mov ecx, dword [esi+16]
|
|
mov dword [bootboot.initrd_size], ecx
|
|
add esi, 32
|
|
cmp word [esi], 08b1fh
|
|
je .initrdrom
|
|
; copy from ROM to RAM
|
|
mov edi, dword [bootboot.initrd_ptr]
|
|
repnz movsb
|
|
jmp .noinflate
|
|
@@: add esi, 2048
|
|
cmp esi, 0F4000h
|
|
jb .nextrom
|
|
|
|
;---- notify raspbootcom / USBImager to send the initrd over serial line ----
|
|
cmp word [400h], 0
|
|
jz .getgpt
|
|
|
|
mov al, 3
|
|
call uart_send
|
|
call uart_send
|
|
call uart_send
|
|
|
|
; wait for response with timeout
|
|
mov ah, al
|
|
mov cx, 10000
|
|
mov dx, word [400h]
|
|
add dx, 5
|
|
@@: dec cx
|
|
jz .getgpt
|
|
pause
|
|
in al, dx
|
|
and al, 1
|
|
jz @b
|
|
|
|
DBG32 dbg_serial
|
|
|
|
; read the initrd's size
|
|
mov edi, bootboot.initrd_size
|
|
call uart_getc
|
|
call uart_getc
|
|
call uart_getc
|
|
call uart_getc
|
|
mov ecx, dword [bootboot.initrd_size]
|
|
; send negative or positive acknowledge
|
|
cmp ecx, 32
|
|
jb .se
|
|
cmp ecx, INITRD_MAXSIZE*1024*1024
|
|
jb .ok
|
|
.se: mov al, 'S'
|
|
call uart_send
|
|
mov al, 'E'
|
|
call uart_send
|
|
jmp .getgpt
|
|
.ok: mov al, 'O'
|
|
call uart_send
|
|
mov al, 'K'
|
|
call uart_send
|
|
mov edi, dword [bootboot.initrd_ptr]
|
|
; read in the image
|
|
@@: call uart_getc
|
|
dec ecx
|
|
jnz @b
|
|
jmp .initrdloaded
|
|
|
|
;---- read GPT -----
|
|
.getgpt: xor eax, eax
|
|
xor edi, edi
|
|
prot_readsector
|
|
if BBDEBUG eq 1
|
|
cmp byte [iscdrom], 0
|
|
jz @f
|
|
DBG32 dbg_cdrom
|
|
jmp .isgpt
|
|
@@: DBG32 dbg_gpt
|
|
.isgpt:
|
|
end if
|
|
mov esi, 0A000h+512
|
|
cmp dword [esi], 'EFI '
|
|
je @f
|
|
.nogpt: mov esi, nogpt
|
|
jmp prot_diefunc
|
|
@@: mov edi, 0B000h
|
|
mov ebx, edi
|
|
mov ecx, 896
|
|
repnz movsd
|
|
mov esi, ebx
|
|
mov ecx, dword [esi+80] ;number of entries
|
|
mov ebx, dword [esi+84] ;size of one entry
|
|
add esi, 512
|
|
mov edx, esi ;first entry
|
|
mov dword [gpt_ent], ebx
|
|
mov dword [gpt_num], ecx
|
|
mov dword [gpt_ptr], edx
|
|
; first, look for a partition with bootable flag
|
|
mov esi, edx
|
|
@@: cmp dword [esi], 0 ;failsafe, jump to parttype search
|
|
jne .notz
|
|
cmp dword [esi+32], 0
|
|
jz .nextgpt
|
|
.notz: bt word [esi+48], 2 ;EFI_PART_USED_BY_OS?
|
|
jc .loadesp2
|
|
add esi, ebx
|
|
dec ecx
|
|
jnz @b
|
|
; if none, look for specific partition types
|
|
.nextgpt: mov esi, dword [gpt_ptr]
|
|
mov ebx, dword [gpt_ent]
|
|
mov ecx, dword [gpt_num]
|
|
mov eax, 0C12A7328h
|
|
mov edx, 011D2F81Fh
|
|
@@: cmp dword [esi], eax ;GUID match?
|
|
jne .note
|
|
cmp dword [esi+4], edx
|
|
je .loadesp
|
|
.note: cmp dword [esi], 'OS/Z' ;or OS/Z root partition for this architecture?
|
|
jne .noto
|
|
cmp word [esi+4], 08664h
|
|
jne .noto
|
|
cmp dword [esi+12], 'root'
|
|
je .loadesp
|
|
.noto: add esi, ebx
|
|
dec ecx
|
|
jnz @b
|
|
.nopart: mov esi, nopar
|
|
jmp prot_diefunc
|
|
|
|
; load ESP at free memory hole found
|
|
.loadesp: mov dword [gpt_ptr], esi
|
|
mov dword [gpt_num], ecx
|
|
.loadesp2: mov ecx, dword [esi+40] ;last sector
|
|
mov eax, dword [esi+32] ;first sector
|
|
mov edx, dword [esi+36]
|
|
or edx, edx
|
|
jnz .nextgpt
|
|
or ecx, ecx
|
|
jz .nextgpt
|
|
or eax, eax
|
|
jz .nextgpt
|
|
mov dword [bpb_sec], eax
|
|
;load BPB
|
|
mov edi, dword [bootboot.initrd_ptr]
|
|
mov word [lbapacket.count], 8
|
|
prot_readsector
|
|
|
|
;parse fat on EFI System Partition
|
|
@@: cmp dword [edi + bpb.fst2], 'FAT3'
|
|
je .isfat
|
|
cmp dword [edi + bpb.fst], 'FAT1'
|
|
je .isfat
|
|
;no, then it's an initrd on the entire partition
|
|
or eax, eax
|
|
jz .nopart
|
|
or ecx, ecx
|
|
jz .nopart
|
|
sub ecx, eax
|
|
shl ecx, 9
|
|
mov dword [bootboot.initrd_size], ecx
|
|
; load INITRD from partition
|
|
dec ecx
|
|
shr ecx, 12
|
|
mov edi, dword [bootboot.initrd_ptr]
|
|
@@: add edi, 4096
|
|
prot_readsector
|
|
add eax, 8
|
|
dec ecx
|
|
jnz @b
|
|
jmp .initrdloaded
|
|
|
|
.isfat: cmp word [edi + bpb.bps], 512
|
|
jne .nextgpt
|
|
;calculations
|
|
xor eax, eax
|
|
xor ebx, ebx
|
|
xor ecx, ecx
|
|
xor edx, edx
|
|
mov bx, word [edi + bpb.spf16]
|
|
or bx, bx
|
|
jnz @f
|
|
mov ebx, dword [edi + bpb.spf32]
|
|
@@: mov al, byte [edi + bpb.nf]
|
|
mov cx, word [edi + bpb.rsc]
|
|
;data_sec = numFat*secPerFat
|
|
mul ebx
|
|
;data_sec += reservedSec
|
|
add eax, ecx
|
|
;data_sec += ESPsec
|
|
add eax, dword [bpb_sec]
|
|
mov dword [data_sec], eax
|
|
mov dword [root_sec], eax
|
|
xor eax, eax
|
|
mov al, byte [edi + bpb.spc]
|
|
mov dword [clu_sec], eax
|
|
;FAT16
|
|
;data_sec += (numRootEnt*32+511)/512
|
|
cmp word [edi + bpb.spf16], 0
|
|
je .fat32bpb
|
|
cmp byte [edi + bpb.fst + 4], '6'
|
|
jne .nextgpt
|
|
xor eax, eax
|
|
mov ax, word [edi + bpb.nr]
|
|
shl eax, 5
|
|
add eax, 511
|
|
shr eax, 9
|
|
add dword [data_sec], eax
|
|
mov byte [fattype], 0
|
|
xor ecx, ecx
|
|
mov cx, word [edi + bpb.spf16]
|
|
jmp .loadfat
|
|
.fat32bpb: ;FAT32
|
|
;root_sec += (rootCluster-2)*secPerCluster
|
|
mov eax, dword [edi + bpb.rc]
|
|
sub eax, 2
|
|
xor edx, edx
|
|
mov ebx, dword [clu_sec]
|
|
mul ebx
|
|
add dword [root_sec], eax
|
|
mov byte [fattype], 1
|
|
mov ecx, dword [edi + bpb.spf32]
|
|
;load FAT
|
|
.loadfat: xor eax, eax
|
|
mov ax, word [edi+bpb.rsc]
|
|
add eax, dword [bpb_sec]
|
|
shr ecx, 3
|
|
inc ecx
|
|
mov edi, 0x10000
|
|
mov word [lbapacket.count], 8
|
|
@@: prot_readsector
|
|
add edi, 4096
|
|
add eax, 8
|
|
dec ecx
|
|
jnz @b
|
|
mov ax, word [clu_sec]
|
|
mov word [lbapacket.count], ax
|
|
|
|
;load root directory
|
|
mov eax, dword [root_sec]
|
|
mov edi, dword [bootboot.initrd_ptr]
|
|
prot_readsector
|
|
|
|
;look for BOOTBOOT directory
|
|
mov esi, edi
|
|
mov eax, 'BOOT'
|
|
mov ecx, 255
|
|
.nextroot: cmp dword [esi], eax
|
|
jne @f
|
|
cmp dword [esi+4], eax
|
|
jne @f
|
|
cmp word [esi+8], ' '
|
|
je .foundroot
|
|
@@: add esi, 32
|
|
cmp byte [esi], 0
|
|
jz .nextgpt
|
|
dec ecx
|
|
jnz .nextroot
|
|
jmp .nextgpt
|
|
.foundroot: xor eax, eax
|
|
cmp byte [fattype], 0
|
|
jz @f
|
|
mov ax, word [esi + fatdir.ch]
|
|
shl eax, 16
|
|
@@: mov ax, word [esi + fatdir.cl]
|
|
;sec = (cluster-2)*secPerCluster+data_sec
|
|
sub eax, 2
|
|
mov ebx, dword [clu_sec]
|
|
mul ebx
|
|
add eax, dword [data_sec]
|
|
mov edi, dword [bootboot.initrd_ptr]
|
|
prot_readsector
|
|
|
|
;look for CONFIG and INITRD
|
|
mov esi, edi
|
|
mov ecx, 255
|
|
mov edx, dword [bkp]
|
|
.nextdir: cmp dword [esi], 'CONF'
|
|
jne .notcfg
|
|
cmp dword [esi+4], 'IG '
|
|
jne .notcfg
|
|
cmp dword [esi+7], ' '
|
|
jne .notcfg
|
|
; load environment from FS0:/BOOTBOOT/CONFIG
|
|
push edx
|
|
push esi
|
|
push edi
|
|
push ecx
|
|
mov ecx, dword [esi + fatdir.size]
|
|
cmp ecx, 4095
|
|
jbe @f
|
|
mov ecx, 4095
|
|
@@: mov dword [core_len], ecx
|
|
xor eax, eax
|
|
cmp byte [fattype], 0
|
|
jz @f
|
|
mov ax, word [esi + fatdir.ch]
|
|
shl eax, 16
|
|
@@: mov ax, word [esi + fatdir.cl]
|
|
mov edi, 9000h
|
|
.nextcfg: push eax
|
|
;sec = (cluster-2)*secPerCluster+data_sec
|
|
sub eax, 2
|
|
mov ebx, dword [clu_sec]
|
|
mov word [lbapacket.count], bx
|
|
mul ebx
|
|
shl ebx, 9
|
|
add eax, dword [data_sec]
|
|
push ebx
|
|
prot_readsector
|
|
pop ebx
|
|
pop eax
|
|
add edi, ebx
|
|
sub ecx, ebx
|
|
js .cfgloaded
|
|
jz .cfgloaded
|
|
;get next cluster from FAT
|
|
cmp byte [fattype], 0
|
|
jz @f
|
|
shl eax, 2
|
|
add eax, 0x10000
|
|
mov eax, dword [eax]
|
|
jmp .nextcfg
|
|
@@: shl eax, 1
|
|
add eax, 0x10000
|
|
mov ax, word [eax]
|
|
and eax, 0FFFFh
|
|
jmp .nextcfg
|
|
.cfgloaded: pop ecx
|
|
pop edi
|
|
pop esi
|
|
pop edx
|
|
xor eax, eax
|
|
mov ecx, 4096
|
|
sub ecx, dword [core_len]
|
|
mov edi, 9000h
|
|
add edi, dword [core_len]
|
|
repnz stosb
|
|
mov dword [core_len], eax
|
|
mov byte [9FFFh], al
|
|
jmp .notinit
|
|
.notcfg:
|
|
cmp dword [esi], 'X86_'
|
|
jne @f
|
|
cmp dword [esi+4], '64 '
|
|
je .altinitrd
|
|
@@: cmp dword [esi], 'INIT'
|
|
jne .notinit
|
|
cmp dword [esi+4], 'RD '
|
|
jne .notinit
|
|
cmp dword [esi+7], edx
|
|
jne .notinit
|
|
|
|
.altinitrd: mov ecx, dword [esi + fatdir.size]
|
|
mov dword [bootboot.initrd_size], ecx
|
|
xor eax, eax
|
|
cmp byte [fattype], 0
|
|
jz @f
|
|
mov ax, word [esi + fatdir.ch]
|
|
shl eax, 16
|
|
@@: mov ax, word [esi + fatdir.cl]
|
|
jmp .loadinitrd
|
|
|
|
.notinit: add esi, 32
|
|
cmp byte [esi], 0
|
|
jz .loadinitrd
|
|
dec ecx
|
|
jnz .nextdir
|
|
.noinitrd: mov esi, nord
|
|
jmp prot_diefunc
|
|
|
|
;load cluster chain, eax=cluster, ecx=size
|
|
.loadinitrd:
|
|
mov edi, dword [bootboot.initrd_ptr]
|
|
.nextclu: push eax
|
|
;sec = (cluster-2)*secPerCluster+data_sec
|
|
sub eax, 2
|
|
mov ebx, dword [clu_sec]
|
|
mov word [lbapacket.count], bx
|
|
mul ebx
|
|
shl ebx, 9
|
|
add eax, dword [data_sec]
|
|
push ebx
|
|
prot_readsector
|
|
pop ebx
|
|
pop eax
|
|
add edi, ebx
|
|
sub ecx, ebx
|
|
js .initrdloaded
|
|
jz .initrdloaded
|
|
;get next cluster from FAT
|
|
cmp byte [fattype], 0
|
|
jz @f
|
|
shl eax, 2
|
|
add eax, 0x10000
|
|
mov eax, dword [eax]
|
|
jmp .nextclu
|
|
@@: shl eax, 1
|
|
add eax, 0x10000
|
|
mov ax, word [eax]
|
|
and eax, 0FFFFh
|
|
jmp .nextclu
|
|
|
|
.initrdloaded:
|
|
DBG32 dbg_initrd
|
|
mov esi, dword [bootboot.initrd_ptr]
|
|
.initrdrom:
|
|
mov edi, dword [bootboot.initrd_ptr]
|
|
cmp word [esi], 08b1fh
|
|
jne .noinflate
|
|
DBG32 dbg_gzinitrd
|
|
mov ebx, esi
|
|
mov eax, dword [bootboot.initrd_size]
|
|
add ebx, eax
|
|
sub ebx, 4
|
|
mov ecx, dword [ebx]
|
|
mov dword [bootboot.initrd_size], ecx
|
|
add edi, eax
|
|
add edi, 4095
|
|
shr edi, 12
|
|
shl edi, 12
|
|
add eax, ecx
|
|
cmp eax, (INITRD_MAXSIZE+2)*1024*1024
|
|
jb @f
|
|
mov esi, nogzmem
|
|
jmp prot_diefunc
|
|
@@: mov dword [bootboot.initrd_ptr], edi
|
|
; inflate initrd
|
|
xor eax, eax
|
|
add esi, 2
|
|
lodsb
|
|
cmp al, 8
|
|
jne tinf_err
|
|
lodsb
|
|
mov bl, al
|
|
add esi, 6
|
|
test bl, 4
|
|
jz @f
|
|
lodsw
|
|
add esi, eax
|
|
@@: test bl, 8
|
|
jz .noname
|
|
@@: lodsb
|
|
or al, al
|
|
jnz @b
|
|
.noname: test bl, 16
|
|
jz .nocmt
|
|
@@: lodsb
|
|
or al, al
|
|
jnz @b
|
|
.nocmt: test bl, 2
|
|
jz @f
|
|
add esi, 2
|
|
@@: call tinf_uncompress
|
|
.noinflate:
|
|
;round up to page size
|
|
mov eax, dword [bootboot.initrd_size]
|
|
add eax, 4095
|
|
shr eax, 12
|
|
shl eax, 12
|
|
mov dword [bootboot.initrd_size], eax
|
|
|
|
;do we have an environment configuration?
|
|
mov ebx, 9000h
|
|
cmp byte [ebx], 0
|
|
jnz .parsecfg
|
|
|
|
;-----load /sys/config------
|
|
mov edx, fsdrivers
|
|
.nextfs1: xor ebx, ebx
|
|
mov bx, word [edx]
|
|
or bx, bx
|
|
jz .errfs1
|
|
mov esi, dword [bootboot.initrd_ptr]
|
|
mov ecx, dword [bootboot.initrd_size]
|
|
add ecx, esi
|
|
mov edi, cfgfile
|
|
push edx
|
|
call ebx
|
|
pop edx
|
|
or ecx, ecx
|
|
jnz .fscfg
|
|
add edx, 2
|
|
jmp .nextfs1
|
|
.fscfg: mov edi, 9000h
|
|
add ecx, 3
|
|
shr ecx, 2
|
|
repnz movsd
|
|
.errfs1:
|
|
;do we have an environment configuration?
|
|
mov ebx, 9000h
|
|
cmp byte [ebx], 0
|
|
jz .noconf
|
|
|
|
;parse
|
|
.parsecfg: push ebx
|
|
DBG32 dbg_env
|
|
pop esi
|
|
jmp .getnext
|
|
|
|
;skip comments
|
|
.nextvar: cmp byte[esi], '#'
|
|
je .skipcom
|
|
cmp word[esi], '//'
|
|
jne @f
|
|
add esi, 2
|
|
.skipcom: lodsb
|
|
cmp al, 10
|
|
je .getnext
|
|
cmp al, 13
|
|
je .getnext
|
|
or al, al
|
|
jz .parseend
|
|
cmp esi, 0A000h
|
|
ja .parseend
|
|
jmp .skipcom
|
|
@@: cmp word[esi], '/*'
|
|
jne @f
|
|
.skipcom2: inc esi
|
|
cmp word [esi-2], '*/'
|
|
je .getnext
|
|
cmp byte [esi], 0
|
|
jz .parseend
|
|
cmp esi, 0A000h
|
|
ja .parseend
|
|
jmp .skipcom2
|
|
;only match on beginning of line
|
|
@@: cmp esi, 9000h
|
|
je @f
|
|
cmp byte [esi-1], ' '
|
|
je @f
|
|
cmp byte [esi-1], 13
|
|
jae .next
|
|
;parse screen dimensions
|
|
@@: cmp dword[esi], 'scre'
|
|
jne @f
|
|
cmp word[esi+4], 'en'
|
|
jne @f
|
|
cmp byte[esi+6], '='
|
|
jne @f
|
|
add esi, 7
|
|
call prot_dec2bin
|
|
mov dword [reqwidth], eax
|
|
inc esi
|
|
call prot_dec2bin
|
|
mov dword [reqheight], eax
|
|
jmp .getnext
|
|
;get kernel's filename
|
|
@@: cmp dword[esi], 'kern'
|
|
jne @f
|
|
cmp word[esi+4], 'el'
|
|
jne @f
|
|
cmp byte[esi+6], '='
|
|
jne @f
|
|
add esi, 7
|
|
mov edi, kernel
|
|
.copy: lodsb
|
|
or al, al
|
|
jz .copyend
|
|
cmp al, ' '
|
|
jz .copyend
|
|
cmp al, 13
|
|
jbe .copyend
|
|
cmp esi, 0A000h
|
|
ja .copyend
|
|
cmp edi, loader_end-1
|
|
jae .copyend
|
|
stosb
|
|
jmp .copy
|
|
.copyend: xor al, al
|
|
stosb
|
|
jmp .getnext
|
|
@@: cmp dword[esi], 'nosm'
|
|
jne .next
|
|
cmp word[esi+4], 'p='
|
|
jne .next
|
|
cmp byte[esi+6], '1'
|
|
jne .next
|
|
mov byte[nosmp], 1
|
|
.next: inc esi
|
|
;failsafe
|
|
.getnext: cmp esi, 0A000h
|
|
jae .parseend
|
|
cmp byte [esi], 0
|
|
je .parseend
|
|
;skip white spaces
|
|
cmp byte [esi], ' '
|
|
je @b
|
|
cmp byte [esi], 13
|
|
jbe @b
|
|
jmp .nextvar
|
|
.noconf: mov edi, ebx
|
|
mov ecx, 1024
|
|
xor eax, eax
|
|
repnz stosd
|
|
mov dword [ebx+0], '// N'
|
|
mov dword [ebx+4], '/A' or (10 shl 16)
|
|
.parseend:
|
|
|
|
;-----load /sys/core------
|
|
mov edx, fsdrivers
|
|
.nextfs: xor ebx, ebx
|
|
mov bx, word [edx]
|
|
or bx, bx
|
|
jz .errfs
|
|
mov esi, dword [bootboot.initrd_ptr]
|
|
mov ecx, dword [bootboot.initrd_size]
|
|
add ecx, esi
|
|
mov edi, kernel
|
|
push edx
|
|
call ebx
|
|
pop edx
|
|
or ecx, ecx
|
|
jnz .coreok
|
|
add edx, 2
|
|
jmp .nextfs
|
|
.errfs2: mov esi, nocore
|
|
jmp prot_diefunc
|
|
.errfs: ; if all drivers failed, search for the first elf executable
|
|
DBG32 dbg_scan
|
|
mov esi, dword [bootboot.initrd_ptr]
|
|
mov ecx, dword [bootboot.initrd_size]
|
|
add ecx, esi
|
|
dec esi
|
|
@@: inc esi
|
|
cmp esi, ecx
|
|
jae .errfs2
|
|
cmp dword [esi], 5A2F534Fh ; OS/Z magic
|
|
je .alt
|
|
cmp dword [esi], 464C457Fh ; ELF magic
|
|
je .alt
|
|
cmp word [esi], 5A4Dh ; MZ magic
|
|
jne @b
|
|
mov eax, dword [esi+0x3c]
|
|
cmp eax, 65536
|
|
jnl @b
|
|
add eax, esi
|
|
cmp dword [eax], 00004550h ; PE magic
|
|
jne @b
|
|
cmp word [eax+4], 8664h ; x86_64
|
|
jne @b
|
|
cmp word [eax+20], 20Bh
|
|
jne @b
|
|
.alt: cmp word [esi+4], 0102h ;lsb 64 bit
|
|
jne @b
|
|
cmp word [esi+18], 62 ;x86_64
|
|
jne @b
|
|
cmp word [esi+0x38], 0 ;e_phnum > 0
|
|
jz @b
|
|
.coreok:
|
|
; parse PE
|
|
cmp word [esi], 5A4Dh ; MZ magic
|
|
jne .tryelf
|
|
mov ebx, esi
|
|
cmp dword [esi+0x3c], 65536
|
|
jnl .badcore
|
|
add esi, dword [esi+0x3c]
|
|
cmp dword [esi], 00004550h ; PE magic
|
|
jne .badcore
|
|
cmp word [esi+4], 8664h ; x86_64 architecture
|
|
jne .badcore
|
|
cmp word [esi+20], 20Bh ; PE32+ format
|
|
jne .badcore
|
|
|
|
DBG32 dbg_pe
|
|
|
|
mov eax, dword [esi+36] ; entry point
|
|
mov dword [entrypoint], eax
|
|
mov dword [entrypoint+4], 0FFFFFFFFh
|
|
mov ecx, eax
|
|
sub ecx, dword [esi+40] ; - code base
|
|
add ecx, dword [esi+24] ; + text size
|
|
add ecx, dword [esi+28] ; + data size
|
|
mov edx, dword [esi+32] ; bss size
|
|
shr eax, 31
|
|
jz .badcore
|
|
jmp .mkcore
|
|
|
|
; parse ELF
|
|
.tryelf: cmp dword [esi], 5A2F534Fh ; OS/Z magic
|
|
je @f
|
|
cmp dword [esi], 464C457Fh ; ELF magic
|
|
jne .badcore
|
|
@@: cmp word [esi+4], 0102h ;lsb 64 bit, little endian
|
|
jne .badcore
|
|
cmp word [esi+18], 62 ;x86_64 architecture
|
|
je @f
|
|
.badcore: mov esi, badcore
|
|
jmp prot_diefunc
|
|
@@:
|
|
DBG32 dbg_elf
|
|
|
|
mov ebx, esi
|
|
mov eax, dword [esi+0x18]
|
|
mov dword [entrypoint], eax
|
|
mov eax, dword [esi+0x18+4]
|
|
mov dword [entrypoint+4], eax
|
|
;parse ELF binary
|
|
mov cx, word [esi+0x38] ; program header entries phnum
|
|
mov eax, dword [esi+0x20] ; program header
|
|
add esi, eax
|
|
sub esi, 56
|
|
inc cx
|
|
.nextph: add esi, 56
|
|
dec cx
|
|
jz .badcore
|
|
cmp word [esi], 1 ; p_type, loadable
|
|
jne .nextph
|
|
cmp word [esi+22], 0FFFFh ; p_vaddr == negative address
|
|
jne .nextph
|
|
;got it
|
|
add ebx, dword [esi+8] ; + P_offset
|
|
mov ecx, dword [esi+32] ; p_filesz
|
|
; hack to keep symtab and strtab for shared libraries
|
|
cmp byte [ebx+16], 3
|
|
jne @f
|
|
add ecx, 04000h
|
|
@@: mov edx, dword [esi+40] ; p_memsz
|
|
sub edx, ecx
|
|
|
|
;ebx=ptr to core segment, ecx=segment size, edx=bss size
|
|
.mkcore: or ecx, ecx
|
|
jz .badcore
|
|
mov eax, ecx
|
|
add eax, edx
|
|
cmp eax, 2*1024*1024 - 256*1024 - 2*4096; 2M minus stack for 256 cores minus bootboot and environment
|
|
jl @f
|
|
mov esi, bigcore
|
|
jmp prot_diefunc
|
|
@@: mov edi, dword [bootboot.initrd_ptr]
|
|
add edi, dword [bootboot.initrd_size]
|
|
mov dword [core_ptr], edi
|
|
mov dword [core_len], ecx
|
|
;copy code from segment after initrd
|
|
mov esi, ebx
|
|
mov ebx, ecx
|
|
and bl, 3
|
|
shr ecx, 2
|
|
repnz movsd
|
|
or bl, bl
|
|
jz @f
|
|
mov cl, bl
|
|
repnz movsb
|
|
;zero out bss
|
|
@@: or edx, edx
|
|
jz @f
|
|
add dword [core_len], edx
|
|
xor eax, eax
|
|
mov ecx, edx
|
|
and dl, 3
|
|
shr ecx, 2
|
|
repnz stosd
|
|
or dl, dl
|
|
jz @f
|
|
mov cl, dl
|
|
repnz stosb
|
|
;round up to page size
|
|
@@: mov eax, dword [core_len]
|
|
add eax, 4095
|
|
shr eax, 12
|
|
shl eax, 12
|
|
mov dword [core_len], eax
|
|
|
|
;exclude initrd area and core from free mmap
|
|
mov esi, bootboot.mmap
|
|
mov ebx, dword [bootboot.initrd_ptr]
|
|
mov edx, dword [core_ptr]
|
|
add edx, eax
|
|
mov cx, 248
|
|
; initrd+core (ebx..edx)
|
|
.nextfree: cmp dword [esi], ebx
|
|
ja .excludeok
|
|
mov eax, dword [esi+8]
|
|
and al, 0F0h
|
|
add eax, dword [esi]
|
|
cmp edx, eax
|
|
ja .notini
|
|
; +--------------+
|
|
; #######
|
|
cmp dword [esi], ebx
|
|
jne .splitmem
|
|
; ptr = initrd_ptr+initrd_size+core_len
|
|
mov dword [esi], edx
|
|
sub edx, ebx
|
|
and dl, 0F0h
|
|
; size -= initrd_size+core_len
|
|
sub dword [esi+8], edx
|
|
jmp .excludeok
|
|
; +--+ +----------+
|
|
; #######
|
|
.splitmem: mov edi, bootboot.magic
|
|
add edi, dword [bootboot.size]
|
|
add dword [bootboot.size], 16
|
|
@@: mov eax, dword [edi-16]
|
|
mov dword [edi], eax
|
|
mov eax, dword [edi-12]
|
|
mov dword [edi+4], eax
|
|
mov eax, dword [edi-8]
|
|
mov dword [edi+8], eax
|
|
mov eax, dword [edi-4]
|
|
mov dword [edi+12], eax
|
|
sub edi, 16
|
|
cmp edi, esi
|
|
ja @b
|
|
mov eax, ebx
|
|
sub eax, dword [esi]
|
|
sub dword [esi+24], eax
|
|
inc al
|
|
mov dword [esi+8], eax
|
|
mov dword [esi+16], edx
|
|
sub edx, ebx
|
|
sub dword [esi+24], edx
|
|
jmp .excludeok
|
|
.notini: add esi, 16
|
|
dec cx
|
|
jnz .nextfree
|
|
.excludeok:
|
|
; -------- SMP ---------
|
|
; clear LAPIC address and logical core id list
|
|
mov edi, lapic_ptr
|
|
mov ecx, 512/4+1
|
|
xor eax, eax
|
|
repnz stosd
|
|
; clear flags
|
|
mov byte [bsp_done], al
|
|
|
|
cmp byte [nosmp], al
|
|
jne .nosmp
|
|
|
|
; try ACPI first
|
|
mov esi, dword [bootboot.acpi_ptr]
|
|
or esi, esi
|
|
jz .trymp
|
|
mov edx, 4
|
|
cmp byte [esi], 'X' ; XSDT has 8 bytes pointers, but we can only access 4G
|
|
jne @f
|
|
mov edx, 8
|
|
@@: mov ecx, dword [esi+4]
|
|
add esi, 024h
|
|
sub ecx, 024h
|
|
.nextsdt: mov ebx, dword [esi]
|
|
add esi, edx
|
|
cmp dword [ebx], 'APIC' ; look for MADT
|
|
je .madt
|
|
sub ecx, edx
|
|
or ecx, ecx
|
|
jz .trymp
|
|
jmp .nextsdt
|
|
; MADT found.
|
|
.madt: mov eax, dword [ebx+24h]
|
|
mov dword [lapic_ptr], eax ; madt.lapic_address
|
|
mov ecx, dword [ebx+4]
|
|
add ecx, ebx
|
|
add ebx, 2ch
|
|
mov edi, lapic_ids
|
|
.nextmadtentry:
|
|
cmp word [bootboot.numcores], 255
|
|
jae .acpidone
|
|
cmp byte [ebx], 0 ; madt_entry.type: is it a Local APIC Processor?
|
|
jne @f
|
|
mov al, byte [ebx+4] ; madt_entry.lapicproc.flag & ENABLED
|
|
and al, 1
|
|
jz .badmadt
|
|
xor ax, ax
|
|
mov al, byte [ebx+3] ; madt_entry.lapicproc.lapicid
|
|
cmp al, 0FFh
|
|
je .badmadt
|
|
stosw ; ACPI table holds 1 byte id, but internally we have 2 bytes
|
|
inc word [bootboot.numcores]
|
|
jmp @f
|
|
.badmadt: mov byte [bad_madt], 1
|
|
@@: xor eax, eax
|
|
mov al, byte [ebx+1] ; madt_entry.size
|
|
or al, al
|
|
jz .acpidone
|
|
add ebx, eax
|
|
cmp ebx, ecx
|
|
jae .acpidone
|
|
jmp .nextmadtentry
|
|
|
|
.trymp: ; in lack of ACPI, try legacy MP structures
|
|
mov esi, dword [bootboot.mp_ptr]
|
|
or esi, esi
|
|
jz .acpidone
|
|
mov esi, dword [esi+4]
|
|
cmp dword [esi], 'PCMP'
|
|
jne .acpidone
|
|
mov eax, dword [esi+36] ; pcmp.lapic_address
|
|
mov dword [lapic_ptr], eax
|
|
mov cx, word [esi+34] ; pcmp.numentries
|
|
add esi, 44 ; pcmp header length
|
|
mov edi, lapic_ids
|
|
.nextpcmpentry:
|
|
cmp word [bootboot.numcores], 255
|
|
jae .acpidone
|
|
cmp byte [esi], 0 ; pcmp_entry.type: is it a Local APIC Processor?
|
|
jne @f
|
|
xor ax, ax
|
|
mov al, byte [esi+1] ; pcmp_entry.lapicproc.lapicid
|
|
stosw ; PCMP has 1 byte id, but we use 2 bytes internally
|
|
inc word [bootboot.numcores]
|
|
add esi, 12
|
|
@@: add esi, 8
|
|
dec cx
|
|
jnz .nextpcmpentry
|
|
.acpidone:
|
|
; failsafe
|
|
cmp dword [lapic_ptr], 0
|
|
jz @f
|
|
cmp word [bootboot.numcores], 1
|
|
ja .smpok
|
|
@@: mov word [bootboot.numcores], 1
|
|
mov ax, word [bootboot.bspid]
|
|
mov word [lapic_ids], ax
|
|
mov dword [lapic_ptr], 0
|
|
jmp .stks
|
|
.smpok:
|
|
if BBDEBUG eq 1
|
|
xor eax, eax
|
|
mov dword [gpt_ptr], eax
|
|
mov dword [gpt_num], eax
|
|
prot_realmode
|
|
mov bx, word [bootboot.numcores]
|
|
mov di, gpt_ptr
|
|
|
|
mov cx, 100
|
|
mov dx, bx
|
|
cmp bx, cx
|
|
jl @f
|
|
mov ax, bx
|
|
xor dx, dx
|
|
div cx
|
|
add al, '0'
|
|
stosb
|
|
@@: mov cx, 10
|
|
mov ax, dx
|
|
xor dx, dx
|
|
div cx
|
|
cmp bx, cx
|
|
jl @f
|
|
add al, '0'
|
|
stosb
|
|
@@: mov al, dl
|
|
add al, '0'
|
|
stosb
|
|
xor al, al
|
|
stosb
|
|
|
|
mov si, dbg_smp
|
|
call real_printfunc
|
|
mov si, gpt_ptr
|
|
call real_printfunc
|
|
cmp byte [bad_madt], 0
|
|
jz @f
|
|
mov si, dbg_madt
|
|
call real_printfunc
|
|
@@: mov si, crlf
|
|
call real_printfunc
|
|
real_protmode
|
|
end if
|
|
.stks: ; remove core stacks from memory map
|
|
xor eax, eax
|
|
mov ax, word [bootboot.numcores]
|
|
shl eax, 10
|
|
add eax, 0FFFh ; round up to page size
|
|
and ax, 0F000h
|
|
mov edi, bootboot.mmap
|
|
add dword [edi], eax
|
|
sub dword [edi+8], eax
|
|
|
|
; ------- set video resolution -------
|
|
prot_realmode
|
|
|
|
DBG dbg_vesa
|
|
|
|
xor ax, ax
|
|
mov es, ax
|
|
;get VESA VBE2.0 info
|
|
mov ax, 4f00h
|
|
mov di, 0A000h
|
|
mov dword [di], 'VBE2'
|
|
;this call requires a big stack
|
|
push ds
|
|
push es
|
|
int 10h
|
|
pop es
|
|
pop ds
|
|
cmp ax, 004fh
|
|
je @f
|
|
.viderr: mov si, novbe
|
|
jmp real_diefunc
|
|
;read dword pointer and copy string to 1st 64k
|
|
;available video modes
|
|
@@: xor esi, esi
|
|
xor edi, edi
|
|
mov si, word [0A000h+0Eh]
|
|
mov ax, word [0A000h+10h]
|
|
mov ds, ax
|
|
xor ax, ax
|
|
mov es, ax
|
|
mov di, 0A000h+400h
|
|
mov cx, 64
|
|
@@: lodsw
|
|
cmp ax, 0ffffh
|
|
je @f
|
|
or ax, ax
|
|
jz @f
|
|
stosw
|
|
dec cx
|
|
jnz @b
|
|
@@: xor ax, ax
|
|
stosw
|
|
;iterate on modes
|
|
mov si, 0A000h+400h
|
|
.nextmode: mov di, 0A000h+800h
|
|
xor ax, ax
|
|
mov word [0A000h+802h], ax ; vbe mode
|
|
lodsw
|
|
or ax, ax
|
|
jz .viderr
|
|
mov cx, ax
|
|
mov ax, 4f01h
|
|
push bx
|
|
push cx
|
|
push si
|
|
push di
|
|
push ds
|
|
push es
|
|
int 10h
|
|
pop es
|
|
pop ds
|
|
pop di
|
|
pop si
|
|
pop cx
|
|
pop bx
|
|
cmp ax, 004fh
|
|
jne .viderr
|
|
bts cx, 13
|
|
bts cx, 14
|
|
mov ax, word [0A000h+800h] ; vbe flags
|
|
and ax, VBE_MODEFLAGS
|
|
cmp ax, VBE_MODEFLAGS
|
|
jne .nextmode
|
|
;check memory model (direct)
|
|
cmp byte [0A000h+81bh], 6
|
|
jne .nextmode
|
|
;check bpp
|
|
cmp byte [0A000h+819h], 32
|
|
jne .nextmode
|
|
;check min width
|
|
mov ax, word [reqwidth]
|
|
cmp ax, 640
|
|
ja @f
|
|
mov ax, 640
|
|
@@: cmp word [0A000h+812h], ax
|
|
jne .nextmode
|
|
;check min height
|
|
mov ax, word [reqheight]
|
|
cmp ax, 480
|
|
ja @f
|
|
mov ax, 480
|
|
@@: cmp word [0A000h+814h], ax
|
|
jb .nextmode
|
|
;match? go no further
|
|
.match: xor edx, edx
|
|
xor ebx, ebx
|
|
xor eax, eax
|
|
mov bx, word [0A000h+810h]
|
|
mov word [bootboot.fb_scanline], bx
|
|
mov ax, word [0A000h+812h]
|
|
mov word [bootboot.fb_width], ax
|
|
mov ax, word [0A000h+814h]
|
|
mov word [bootboot.fb_height], ax
|
|
mul ebx
|
|
mov dword [bootboot.fb_size], eax
|
|
mov eax, dword [0A000h+828h]
|
|
mov dword [bootboot.fb_ptr], eax
|
|
mov byte [bootboot.fb_type],FB_ARGB ; blue offset
|
|
cmp byte [0A000h+824h], 0
|
|
je @f
|
|
mov byte [bootboot.fb_type],FB_RGBA
|
|
cmp byte [0A000h+824h], 8
|
|
je @f
|
|
mov byte [bootboot.fb_type],FB_ABGR
|
|
cmp byte [0A000h+824h], 16
|
|
je @f
|
|
mov byte [bootboot.fb_type],FB_BGRA
|
|
@@: ; set video mode
|
|
mov bx, cx
|
|
bts bx, 14 ;flat linear
|
|
mov ax, 4f02h
|
|
push ds
|
|
push es
|
|
int 10h
|
|
pop es
|
|
pop ds
|
|
cmp ax, 004fh
|
|
jne .viderr
|
|
;no debug output after this point
|
|
|
|
;inform firmware that we're about to leave it's realm
|
|
mov ax, 0EC00h
|
|
mov bx, 2 ; 64 bit
|
|
int 15h
|
|
real_protmode
|
|
|
|
; -------- paging ---------
|
|
;map core at higher half of memory
|
|
;address 0xffffffffffe00000
|
|
xor eax, eax
|
|
mov edi, 0A000h
|
|
mov ecx, (14000h+256*1024-0A000h)/4
|
|
repnz stosd
|
|
|
|
;PML4
|
|
mov edi, 0A000h
|
|
;pointer to 2M PDPE (first 4G RAM identity mapped)
|
|
mov dword [edi], 0E003h
|
|
;pointer to 4k PDPE (core mapped at -2M)
|
|
mov dword [edi+4096-8], 0B003h
|
|
|
|
;4K PDPE
|
|
mov edi, 0B000h
|
|
mov dword [edi+4096-8], 0C003h
|
|
;4K PDE
|
|
mov edi, 0C000h+3840
|
|
mov eax, dword[bootboot.fb_ptr] ;map framebuffer
|
|
mov al,83h
|
|
mov ecx, 31
|
|
@@: stosd
|
|
add edi, 4
|
|
add eax, 2*1024*1024
|
|
dec ecx
|
|
jnz @b
|
|
mov dword [0C000h+4096-8], 0D003h
|
|
|
|
;4K PT
|
|
mov dword[0D000h], 08001h ;map bootboot
|
|
mov dword[0D008h], 09001h ;map configuration
|
|
mov edi, 0D010h
|
|
mov eax, dword[core_ptr] ;map core text segment
|
|
inc eax
|
|
mov ecx, dword[core_len]
|
|
shr ecx, 12
|
|
inc ecx
|
|
@@: stosd
|
|
add edi, 4
|
|
add eax, 4096
|
|
dec ecx
|
|
jnz @b
|
|
;map core stacks (one page per 4 cores)
|
|
mov edi, 0DFF8h
|
|
mov eax, 014003h
|
|
mov cx, word [bootboot.numcores]
|
|
add cx, 3
|
|
shr cx, 2
|
|
@@: mov dword[edi], eax
|
|
sub edi, 8
|
|
add eax, 1000h
|
|
dec cx
|
|
jnz @b
|
|
|
|
;identity mapping
|
|
;2M PDPE
|
|
mov edi, 0E000h
|
|
mov dword [edi], 0F003h
|
|
mov dword [edi+8], 010003h
|
|
mov dword [edi+16], 011003h
|
|
mov dword [edi+24], 012003h
|
|
;2M PDE
|
|
mov edi, 0F000h
|
|
xor eax, eax
|
|
mov al, 83h
|
|
mov ecx, 512* 4;G RAM
|
|
@@: stosd
|
|
add edi, 4
|
|
add eax, 2*1024*1024
|
|
dec ecx
|
|
jnz @b
|
|
;first 2M mapped by page
|
|
mov dword [0F000h], 013003h
|
|
mov edi, 013000h
|
|
mov eax, 3
|
|
mov ecx, 512
|
|
@@: stosd
|
|
add edi, 4
|
|
add eax, 4096
|
|
dec ecx
|
|
jnz @b
|
|
|
|
mov al, 0FFh ;disable PIC
|
|
out 021h, al
|
|
out 0A1h, al
|
|
in al, 70h ;disable NMI
|
|
or al, 80h
|
|
out 70h, al
|
|
|
|
; ------- send INIT IPI and SIPI --------
|
|
cmp word [bootboot.numcores], 2
|
|
jb .nosmp
|
|
cmp dword [lapic_ptr], 0
|
|
jz .nosmp
|
|
|
|
; relocate AP trampoline
|
|
mov esi, ap_trampoline
|
|
mov edi, 7000h
|
|
mov ecx, (ap_start-ap_trampoline+3)/4
|
|
repnz movsd
|
|
|
|
; disable ICMR
|
|
mov al, 070h
|
|
out 22h, al
|
|
in al, 23h
|
|
or al, 1
|
|
out 23h, al
|
|
|
|
; enable Local APIC
|
|
mov esi, dword [lapic_ptr]
|
|
mov al, 1
|
|
shl eax, 24
|
|
mov dword [esi + 0D0h], eax ; logical destination
|
|
xor eax, eax
|
|
sub eax, 1
|
|
mov dword [esi + 0E0h], eax ; destination form
|
|
mov eax, dword [esi + 0F0h] ; spurious + enable
|
|
mov ax, 1FFh
|
|
mov dword [esi + 0F0h], eax
|
|
mov dword [esi + 080h], 0 ; task priority
|
|
; make sure we use the correct Local APIC ID for the BSP
|
|
mov eax, dword [esi + 020h]
|
|
shr eax, 24
|
|
mov word [bootboot.bspid], ax
|
|
|
|
mov ecx, 1Bh ; enable APIC MSR
|
|
rdmsr
|
|
bt eax, 1
|
|
wrmsr
|
|
|
|
mov al, 0fh ; CMOS warm reset code 0A
|
|
out 70h, al
|
|
mov al, 0ah
|
|
out 71h, al
|
|
mov dword [467h], 07000000h ; warm reset vector
|
|
|
|
; use broadcast IPI if MADT is okay (no bcast id and all CPUs enabled)
|
|
cmp byte [bad_madt], 0
|
|
jnz .onebyone
|
|
; send Broadcast INIT IPI
|
|
mov eax, 0C4500h
|
|
mov dword [esi + 300h], eax
|
|
; wait 10 millisec
|
|
prot_sleep 50
|
|
; send Broadcast STARTUP IPI
|
|
mov eax, 0C4607h
|
|
mov dword [esi + 300h], eax
|
|
; wait 200 microsec
|
|
prot_sleep 1
|
|
; send second STARTUP IPI
|
|
mov eax, 0C4607h
|
|
mov dword [esi + 300h], eax
|
|
; wait 200 microsec
|
|
prot_sleep 1
|
|
|
|
jmp .nosmp
|
|
.onebyone:
|
|
|
|
; send IPIs to specific cores one by one
|
|
xor edx, edx
|
|
.initcore: cmp dx, word [bootboot.numcores]
|
|
jae .sipi
|
|
mov esi, edx
|
|
inc edx
|
|
shl esi, 1
|
|
add esi, lapic_ids
|
|
mov bx, word [esi]
|
|
cmp bx, word [bootboot.bspid]
|
|
je .initcore
|
|
shl ebx, 24
|
|
|
|
; clear APIC error
|
|
mov esi, dword [lapic_ptr]
|
|
mov dword [esi + 280h], 0
|
|
mov eax, dword [esi + 280h]
|
|
add esi, 20h
|
|
|
|
; select AP
|
|
@@: pause
|
|
mov eax, dword [esi + 300h]
|
|
bt eax, 12
|
|
jc @b
|
|
mov eax, dword [esi + 310h]
|
|
and eax, 00ffffffh
|
|
or eax, ebx
|
|
mov dword [esi + 310h], eax
|
|
; trigger INIT IPI
|
|
mov eax, dword [esi + 300h]
|
|
and eax, 0fff00000h
|
|
or eax, 00C500h
|
|
mov dword [esi + 300h], eax
|
|
|
|
; wait 200 microsec
|
|
prot_sleep 1
|
|
|
|
; select AP
|
|
@@: pause
|
|
mov eax, dword [esi + 300h]
|
|
bt eax, 12
|
|
jc @b
|
|
mov eax, dword [esi + 310h]
|
|
and eax, 00ffffffh
|
|
or eax, ebx
|
|
mov dword [esi + 310h], eax
|
|
; deassert INIT IPI
|
|
mov eax, dword [esi + 300h]
|
|
and eax, 0fff00000h
|
|
or eax, 008500h
|
|
mov dword [esi + 300h], eax
|
|
jmp .initcore
|
|
.sipi:
|
|
; wait 10 millisec
|
|
prot_sleep 50
|
|
|
|
xor edx, edx
|
|
.nextcore: cmp dx, word [bootboot.numcores]
|
|
jae .nosmp
|
|
mov esi, edx
|
|
inc edx
|
|
shl esi, 1
|
|
add esi, lapic_ids
|
|
mov bx, word [esi]
|
|
cmp bx, word [bootboot.bspid]
|
|
je .nextcore
|
|
shl ebx, 24
|
|
|
|
mov word [ap_done], 0
|
|
|
|
; select AP
|
|
mov esi, dword [lapic_ptr]
|
|
@@: pause
|
|
mov eax, dword [esi + 300h]
|
|
bt eax, 12
|
|
jc @b
|
|
mov eax, dword [esi + 310h]
|
|
and eax, 00ffffffh
|
|
or eax, ebx
|
|
mov dword [esi + 310h], eax
|
|
; send STARTUP IPI
|
|
mov eax, dword [esi + 300h]
|
|
and eax, 0fff0f800h
|
|
or eax, 004607h ; start at 0700:0000h
|
|
mov dword [esi + 300h], eax
|
|
|
|
; wait 10 millisec
|
|
prot_sleep 50
|
|
|
|
; do we need a second SIPI?
|
|
cmp word [ap_done], 0
|
|
jnz .nextcore
|
|
|
|
; select AP
|
|
@@: pause
|
|
mov eax, dword [esi + 300h]
|
|
bt eax, 12
|
|
jc @b
|
|
mov eax, dword [esi + 310h]
|
|
and eax, 00ffffffh
|
|
or eax, ebx
|
|
mov dword [esi + 310h], eax
|
|
; send STARTUP IPI
|
|
mov eax, dword [esi + 300h]
|
|
and eax, 0fff0f800h
|
|
or eax, 004607h
|
|
mov dword [esi + 300h], eax
|
|
|
|
; wait 10 millisec
|
|
prot_sleep 50
|
|
jmp .nextcore
|
|
.nosmp:
|
|
;Enter long mode
|
|
cli
|
|
;release AP spinlock
|
|
lock inc byte [bsp_done]
|
|
|
|
;don't use stack below this line
|
|
longmode_init:
|
|
mov eax, 1101101000b ;Set PAE, MCE, PGE; OSFXSR, OSXMMEXCPT (enable SSE)
|
|
mov cr4, eax
|
|
mov eax, 0A000h
|
|
mov cr3, eax
|
|
mov ecx, 0C0000080h ;EFER MSR
|
|
rdmsr
|
|
or eax, 100h ;enable long mode
|
|
wrmsr
|
|
|
|
mov eax, 0C0000011h ;clear EM, MP (enable SSE) and WP
|
|
mov cr0, eax ;enable paging with cache disabled
|
|
lgdt [GDT64_value] ;read 80 bit address
|
|
jmp 8:.bootboot_startcore
|
|
USE64
|
|
.bootboot_startcore:
|
|
xor rax, rax ;load long mode segments
|
|
mov ax, 10h
|
|
mov ds, ax
|
|
mov es, ax
|
|
mov ss, ax
|
|
mov fs, ax
|
|
mov gs, ax
|
|
; find out our lapic id
|
|
mov eax, dword [lapic_ptr]
|
|
or eax, eax
|
|
jz @f
|
|
mov eax, dword [rax + 020h]
|
|
shr eax, 24
|
|
@@: mov edx, eax
|
|
; get array index for it
|
|
xor rbx, rbx
|
|
mov rsi, lapic_ids
|
|
mov cx, word [bootboot.numcores]
|
|
@@: lodsw
|
|
cmp ax, dx
|
|
je @f
|
|
inc ebx
|
|
dec cx
|
|
jnz @b
|
|
xor rbx, rbx
|
|
@@: mov rdi, rbx
|
|
shl rbx, 10 ; 1k stack for each core
|
|
|
|
; set stack and call _start() in sys/core
|
|
xor rsp, rsp ;sp = core_num * -1024
|
|
sub rsp, rbx
|
|
jmp qword[entrypoint]
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
|
|
USE32
|
|
include "fs.inc"
|
|
include "tinf.inc"
|
|
|
|
;encryption support for FS/Z
|
|
; --- SHA-256 ---
|
|
sha_init: xor eax, eax
|
|
mov dword [sha_l], eax
|
|
mov dword [sha_b], eax
|
|
mov dword [sha_b+4], eax
|
|
mov dword [sha_s ], 06a09e667h
|
|
mov dword [sha_s+ 4], 0bb67ae85h
|
|
mov dword [sha_s+ 8], 03c6ef372h
|
|
mov dword [sha_s+12], 0a54ff53ah
|
|
mov dword [sha_s+16], 0510e527fh
|
|
mov dword [sha_s+20], 09b05688ch
|
|
mov dword [sha_s+24], 01f83d9abh
|
|
mov dword [sha_s+28], 05be0cd19h
|
|
ret
|
|
|
|
; IN: ebx = buffer, ecx = length
|
|
sha_upd: push esi
|
|
or ecx, ecx
|
|
jz .end
|
|
mov esi, ebx
|
|
mov edi, dword [sha_l]
|
|
add edi, sha_d
|
|
; for(;len--;d++) {
|
|
; ctx->d[ctx->l++]=*d;
|
|
.next: movsb
|
|
inc byte [sha_l]
|
|
; if(ctx->l==64) {
|
|
cmp byte [sha_l], 64
|
|
jne @f
|
|
; sha256_t(ctx);
|
|
call sha_final.sha_t
|
|
; SHA_ADD(ctx->b[0],ctx->b[1],512);
|
|
add dword [sha_b], 512
|
|
adc dword [sha_b+4], 0
|
|
; ctx->l=0;
|
|
mov byte [sha_l], 0
|
|
sub edi, 64
|
|
; }
|
|
@@: dec ecx
|
|
jnz .next
|
|
.end: pop esi
|
|
ret
|
|
|
|
; IN: edi = output buffer
|
|
sha_final: push esi
|
|
push edi
|
|
mov ebx, edi
|
|
; i=ctx->l; ctx->d[i++]=0x80;
|
|
mov edi, dword [sha_l]
|
|
mov ecx, edi
|
|
add edi, sha_d
|
|
mov al, 80h
|
|
stosb
|
|
inc ecx
|
|
xor eax, eax
|
|
; if(ctx->l<56) {while(i<56) ctx->d[i++]=0x00;}
|
|
cmp cl, 57
|
|
jae @f
|
|
neg ecx
|
|
add ecx, 56
|
|
repnz stosb
|
|
jmp .padded
|
|
@@: ; else {while(i<64) ctx->d[i++]=0x00;sha256_t(ctx);memset(ctx->d,0,56);}
|
|
neg ecx
|
|
add ecx, 64
|
|
repnz stosb
|
|
call .sha_t
|
|
mov ecx, 56/4
|
|
mov edi, sha_d
|
|
repnz stosd
|
|
.padded: ; SHA_ADD(ctx->b[0],ctx->b[1],ctx->l*8);
|
|
mov eax, dword [sha_l]
|
|
shl eax, 3
|
|
add dword [sha_b], eax
|
|
adc dword [sha_b+4], 0
|
|
; ctx->d[63]=ctx->b[0];ctx->d[62]=ctx->b[0]>>8;ctx->d[61]=ctx->b[0]>>16;ctx->d[60]=ctx->b[0]>>24;
|
|
mov eax, dword [sha_b]
|
|
bswap eax
|
|
mov dword [sha_d+60], eax
|
|
; ctx->d[59]=ctx->b[1];ctx->d[58]=ctx->b[1]>>8;ctx->d[57]=ctx->b[1]>>16;ctx->d[56]=ctx->b[1]>>24;
|
|
mov eax, dword [sha_b+4]
|
|
bswap eax
|
|
mov dword [sha_d+56], eax
|
|
; sha256_t(ctx);
|
|
call .sha_t
|
|
; for(i=0;i<4;i++) {
|
|
; h[i] =(ctx->s[0]>>(24-i*8)); h[i+4] =(ctx->s[1]>>(24-i*8));
|
|
; h[i+8] =(ctx->s[2]>>(24-i*8)); h[i+12]=(ctx->s[3]>>(24-i*8));
|
|
; h[i+16]=(ctx->s[4]>>(24-i*8)); h[i+20]=(ctx->s[5]>>(24-i*8));
|
|
; h[i+24]=(ctx->s[6]>>(24-i*8)); h[i+28]=(ctx->s[7]>>(24-i*8));
|
|
; }
|
|
mov edi, ebx
|
|
mov esi, sha_s
|
|
mov cl, 8
|
|
@@: lodsd
|
|
bswap eax
|
|
stosd
|
|
dec cl
|
|
jnz @b
|
|
pop edi
|
|
pop esi
|
|
ret
|
|
; private func, sha transform
|
|
.sha_t: push esi
|
|
push edi
|
|
push edx
|
|
push ecx
|
|
push ebx
|
|
; for(i=0,j=0;i<16;i++,j+=4) m[i]=(ctx->d[j]<<24)|(ctx->d[j+1]<<16)|(ctx->d[j+2]<<8)|(ctx->d[j+3]);
|
|
mov cl, 16
|
|
mov edi, _m
|
|
mov esi, sha_d
|
|
@@: lodsd
|
|
bswap eax
|
|
stosd
|
|
dec cl
|
|
jnz @b
|
|
; for(;i<64;i++) m[i]=SHA_SIG1(m[i-2])+m[i-7]+SHA_SIG0(m[i-15])+m[i-16];
|
|
mov cl, 48
|
|
; SHA_SIG0[m[i-15]) (SHA_ROTR(x,7)^SHA_ROTR(x,18)^((x)>>3))
|
|
@@: mov eax, dword [edi-15*4]
|
|
mov ebx, eax
|
|
mov edx, eax
|
|
ror eax, 7
|
|
ror ebx, 18
|
|
shr edx, 3
|
|
xor eax, ebx
|
|
xor eax, edx
|
|
; SHA_SIG1(m[i-2]) (SHA_ROTR(x,17)^SHA_ROTR(x,19)^((x)>>10))
|
|
mov ebx, dword [edi-2*4]
|
|
mov edx, ebx
|
|
ror ebx, 17
|
|
ror edx, 19
|
|
xor ebx, edx
|
|
rol edx, 19
|
|
shr edx, 10
|
|
xor ebx, edx
|
|
add eax, ebx
|
|
; m[i-7]
|
|
add eax, dword [edi-7*4]
|
|
; m[i-16]
|
|
add eax, dword [edi-16*4]
|
|
stosd
|
|
dec cl
|
|
jnz @b
|
|
; a=ctx->s[0];b=ctx->s[1];c=ctx->s[2];d=ctx->s[3];
|
|
; e=ctx->s[4];f=ctx->s[5];g=ctx->s[6];h=ctx->s[7];
|
|
xor ecx, ecx
|
|
mov cl, 8
|
|
mov esi, sha_s
|
|
mov edi, _a
|
|
repnz movsd
|
|
; for(i=0;i<64;i++) {
|
|
mov esi, _m
|
|
@@: ; t1=h+SHA_EP1(e)+SHA_CH(e,f,g)+sha256_k[i]+m[i];
|
|
mov eax, dword [_h]
|
|
mov dword [t1], eax
|
|
; SHA_EP1(e) (SHA_ROTR(x,6)^SHA_ROTR(x,11)^SHA_ROTR(x,25))
|
|
mov eax, dword [_e]
|
|
mov ebx, eax
|
|
ror eax, 6
|
|
ror ebx, 11
|
|
xor eax, ebx
|
|
ror ebx, 14 ; 25 = 11+14
|
|
xor eax, ebx
|
|
add dword [t1], eax
|
|
; SHA_CH(e,f,g) (((x)&(y))^(~(x)&(z)))
|
|
mov eax, dword [_e]
|
|
mov ebx, eax
|
|
not ebx
|
|
and eax, dword [_f]
|
|
and ebx, dword [_g]
|
|
xor eax, ebx
|
|
add dword [t1], eax
|
|
; sha256_k[i]
|
|
mov eax, dword [sha256_k+4*ecx]
|
|
add dword [t1], eax
|
|
; m[i]
|
|
lodsd
|
|
add dword [t1], eax
|
|
; t2=SHA_EP0(a)+SHA_MAJ(a,b,c);
|
|
; SHA_EP0(a) (SHA_ROTR(x,2)^SHA_ROTR(x,13)^SHA_ROTR(x,22))
|
|
mov eax, dword [_a]
|
|
mov ebx, eax
|
|
ror eax, 2
|
|
ror ebx, 13
|
|
xor eax, ebx
|
|
ror ebx, 9 ; 22 = 13+9
|
|
xor eax, ebx
|
|
mov dword [t2], eax
|
|
; SHA_MAJ(a,b,c) (((x)&(y))^((x)&(z))^((y)&(z)))
|
|
mov eax, dword [_a]
|
|
mov edx, dword [_c]
|
|
mov ebx, eax
|
|
and eax, dword [_b]
|
|
and ebx, edx
|
|
xor eax, ebx
|
|
mov ebx, dword [_b]
|
|
and ebx, edx
|
|
xor eax, ebx
|
|
add dword [t2], eax
|
|
; h=g;g=f;f=e;e=d+t1;d=c;c=b;b=a;a=t1+t2;
|
|
mov eax, dword [_g]
|
|
mov dword [_h], eax
|
|
mov eax, dword [_f]
|
|
mov dword [_g], eax
|
|
mov eax, dword [_e]
|
|
mov dword [_f], eax
|
|
mov eax, dword [_d]
|
|
add eax, dword [t1]
|
|
mov dword [_e], eax
|
|
mov eax, dword [_c]
|
|
mov dword [_d], eax
|
|
mov eax, dword [_b]
|
|
mov dword [_c], eax
|
|
mov eax, dword [_a]
|
|
mov dword [_b], eax
|
|
mov eax, dword [t1]
|
|
add eax, dword [t2]
|
|
mov dword [_a], eax
|
|
; }
|
|
inc cl
|
|
cmp cl, 64
|
|
jne @b
|
|
; ctx->s[0]+=a;ctx->s[1]+=b;ctx->s[2]+=c;ctx->s[3]+=d;
|
|
; ctx->s[4]+=e;ctx->s[5]+=f;ctx->s[6]+=g;ctx->s[7]+=h;
|
|
mov cl, 8
|
|
mov esi, _a
|
|
mov edi, sha_s
|
|
@@: lodsd
|
|
add dword [edi], eax
|
|
add edi, 4
|
|
dec cl
|
|
jnz @b
|
|
pop ebx
|
|
pop ecx
|
|
pop edx
|
|
pop edi
|
|
pop esi
|
|
xor eax, eax
|
|
ret
|
|
|
|
; --- CRC-32c ---
|
|
; IN: esi = buffer, ecx = length
|
|
; OUT: edx = crc
|
|
crc32_calc: xor edx, edx
|
|
xor eax, eax
|
|
xor ebx, ebx
|
|
or cx, cx
|
|
jz .end
|
|
.next: lodsb
|
|
mov bl, dl
|
|
xor bl, al
|
|
mov eax, edx
|
|
shr edx, 8
|
|
xor edx, dword [crclkp+4*ebx]
|
|
dec cx
|
|
jnz .next
|
|
.end: ret
|
|
|
|
;*********************************************************************
|
|
;* Data *
|
|
;*********************************************************************
|
|
;global descriptor table
|
|
align 16
|
|
GDT_table: dd 0, 0 ;null descriptor
|
|
DATA_PROT = $-GDT_table
|
|
dd 0000FFFFh,00CF9200h ;flat ds
|
|
DATA_BOOT = $-GDT_table
|
|
dd 0000FFFFh,00009200h ;16 bit legacy real mode ds
|
|
CODE_BOOT = $-GDT_table
|
|
dd 0000FFFFh,00009800h ;16 bit legacy real mode cs
|
|
CODE_PROT = $-GDT_table
|
|
dd 0000FFFFh,00CF9A00h ;32 bit prot mode ring0 cs
|
|
dd 00000068h,00CF8900h ;32 bit TSS, not used but required
|
|
GDT_value: dw $-GDT_table-1
|
|
dd GDT_table
|
|
dd 0,0
|
|
align 16
|
|
GDT64_table:dd 0, 0 ;null descriptor
|
|
dd 0000FFFFh,00209800h ;supervisor mode (ring 0) cs
|
|
dd 0000FFFFh,00809200h ;flat data segment
|
|
dd 00000068h,00008900h ;TSS, not used but required by vt-x
|
|
dd 0,0
|
|
GDT64_value:dw $-GDT64_table-1
|
|
dd GDT64_table
|
|
dd 0,0
|
|
|
|
;lookup tables for initrd encryption
|
|
dw 0
|
|
crclkp: dd 000000000h, 0F26B8303h, 0E13B70F7h, 01350F3F4h, 0C79A971Fh, 035F1141Ch, 026A1E7E8h, 0D4CA64EBh
|
|
dd 08AD958CFh, 078B2DBCCh, 06BE22838h, 09989AB3Bh, 04D43CFD0h, 0BF284CD3h, 0AC78BF27h, 05E133C24h
|
|
dd 0105EC76Fh, 0E235446Ch, 0F165B798h, 0030E349Bh, 0D7C45070h, 025AFD373h, 036FF2087h, 0C494A384h
|
|
dd 09A879FA0h, 068EC1CA3h, 07BBCEF57h, 089D76C54h, 05D1D08BFh, 0AF768BBCh, 0BC267848h, 04E4DFB4Bh
|
|
dd 020BD8EDEh, 0D2D60DDDh, 0C186FE29h, 033ED7D2Ah, 0E72719C1h, 0154C9AC2h, 0061C6936h, 0F477EA35h
|
|
dd 0AA64D611h, 0580F5512h, 04B5FA6E6h, 0B93425E5h, 06DFE410Eh, 09F95C20Dh, 08CC531F9h, 07EAEB2FAh
|
|
dd 030E349B1h, 0C288CAB2h, 0D1D83946h, 023B3BA45h, 0F779DEAEh, 005125DADh, 01642AE59h, 0E4292D5Ah
|
|
dd 0BA3A117Eh, 04851927Dh, 05B016189h, 0A96AE28Ah, 07DA08661h, 08FCB0562h, 09C9BF696h, 06EF07595h
|
|
dd 0417B1DBCh, 0B3109EBFh, 0A0406D4Bh, 0522BEE48h, 086E18AA3h, 0748A09A0h, 067DAFA54h, 095B17957h
|
|
dd 0CBA24573h, 039C9C670h, 02A993584h, 0D8F2B687h, 00C38D26Ch, 0FE53516Fh, 0ED03A29Bh, 01F682198h
|
|
dd 05125DAD3h, 0A34E59D0h, 0B01EAA24h, 042752927h, 096BF4DCCh, 064D4CECFh, 077843D3Bh, 085EFBE38h
|
|
dd 0DBFC821Ch, 02997011Fh, 03AC7F2EBh, 0C8AC71E8h, 01C661503h, 0EE0D9600h, 0FD5D65F4h, 00F36E6F7h
|
|
dd 061C69362h, 093AD1061h, 080FDE395h, 072966096h, 0A65C047Dh, 05437877Eh, 04767748Ah, 0B50CF789h
|
|
dd 0EB1FCBADh, 0197448AEh, 00A24BB5Ah, 0F84F3859h, 02C855CB2h, 0DEEEDFB1h, 0CDBE2C45h, 03FD5AF46h
|
|
dd 07198540Dh, 083F3D70Eh, 090A324FAh, 062C8A7F9h, 0B602C312h, 044694011h, 05739B3E5h, 0A55230E6h
|
|
dd 0FB410CC2h, 0092A8FC1h, 01A7A7C35h, 0E811FF36h, 03CDB9BDDh, 0CEB018DEh, 0DDE0EB2Ah, 02F8B6829h
|
|
dd 082F63B78h, 0709DB87Bh, 063CD4B8Fh, 091A6C88Ch, 0456CAC67h, 0B7072F64h, 0A457DC90h, 0563C5F93h
|
|
dd 0082F63B7h, 0FA44E0B4h, 0E9141340h, 01B7F9043h, 0CFB5F4A8h, 03DDE77ABh, 02E8E845Fh, 0DCE5075Ch
|
|
dd 092A8FC17h, 060C37F14h, 073938CE0h, 081F80FE3h, 055326B08h, 0A759E80Bh, 0B4091BFFh, 0466298FCh
|
|
dd 01871A4D8h, 0EA1A27DBh, 0F94AD42Fh, 00B21572Ch, 0DFEB33C7h, 02D80B0C4h, 03ED04330h, 0CCBBC033h
|
|
dd 0A24BB5A6h, 0502036A5h, 04370C551h, 0B11B4652h, 065D122B9h, 097BAA1BAh, 084EA524Eh, 07681D14Dh
|
|
dd 02892ED69h, 0DAF96E6Ah, 0C9A99D9Eh, 03BC21E9Dh, 0EF087A76h, 01D63F975h, 00E330A81h, 0FC588982h
|
|
dd 0B21572C9h, 0407EF1CAh, 0532E023Eh, 0A145813Dh, 0758FE5D6h, 087E466D5h, 094B49521h, 066DF1622h
|
|
dd 038CC2A06h, 0CAA7A905h, 0D9F75AF1h, 02B9CD9F2h, 0FF56BD19h, 00D3D3E1Ah, 01E6DCDEEh, 0EC064EEDh
|
|
dd 0C38D26C4h, 031E6A5C7h, 022B65633h, 0D0DDD530h, 00417B1DBh, 0F67C32D8h, 0E52CC12Ch, 01747422Fh
|
|
dd 049547E0Bh, 0BB3FFD08h, 0A86F0EFCh, 05A048DFFh, 08ECEE914h, 07CA56A17h, 06FF599E3h, 09D9E1AE0h
|
|
dd 0D3D3E1ABh, 021B862A8h, 032E8915Ch, 0C083125Fh, 0144976B4h, 0E622F5B7h, 0F5720643h, 007198540h
|
|
dd 0590AB964h, 0AB613A67h, 0B831C993h, 04A5A4A90h, 09E902E7Bh, 06CFBAD78h, 07FAB5E8Ch, 08DC0DD8Fh
|
|
dd 0E330A81Ah, 0115B2B19h, 0020BD8EDh, 0F0605BEEh, 024AA3F05h, 0D6C1BC06h, 0C5914FF2h, 037FACCF1h
|
|
dd 069E9F0D5h, 09B8273D6h, 088D28022h, 07AB90321h, 0AE7367CAh, 05C18E4C9h, 04F48173Dh, 0BD23943Eh
|
|
dd 0F36E6F75h, 00105EC76h, 012551F82h, 0E03E9C81h, 034F4F86Ah, 0C69F7B69h, 0D5CF889Dh, 027A40B9Eh
|
|
dd 079B737BAh, 08BDCB4B9h, 0988C474Dh, 06AE7C44Eh, 0BE2DA0A5h, 04C4623A6h, 05F16D052h, 0AD7D5351h
|
|
|
|
sha256_k: dd 0428a2f98h, 071374491h, 0b5c0fbcfh, 0e9b5dba5h, 03956c25bh, 059f111f1h, 0923f82a4h, 0ab1c5ed5h
|
|
dd 0d807aa98h, 012835b01h, 0243185beh, 0550c7dc3h, 072be5d74h, 080deb1feh, 09bdc06a7h, 0c19bf174h
|
|
dd 0e49b69c1h, 0efbe4786h, 00fc19dc6h, 0240ca1cch, 02de92c6fh, 04a7484aah, 05cb0a9dch, 076f988dah
|
|
dd 0983e5152h, 0a831c66dh, 0b00327c8h, 0bf597fc7h, 0c6e00bf3h, 0d5a79147h, 006ca6351h, 014292967h
|
|
dd 027b70a85h, 02e1b2138h, 04d2c6dfch, 053380d13h, 0650a7354h, 0766a0abbh, 081c2c92eh, 092722c85h
|
|
dd 0a2bfe8a1h, 0a81a664bh, 0c24b8b70h, 0c76c51a3h, 0d192e819h, 0d6990624h, 0f40e3585h, 0106aa070h
|
|
dd 019a4c116h, 01e376c08h, 02748774ch, 034b0bcb5h, 0391c0cb3h, 04ed8aa4ah, 05b9cca4fh, 0682e6ff3h
|
|
dd 0748f82eeh, 078a5636fh, 084c87814h, 08cc70208h, 090befffah, 0a4506cebh, 0bef9a3f7h, 0c67178f2h
|
|
idt16: dw 3FFh
|
|
dq 0
|
|
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
|
|
reqwidth: dd 1024
|
|
reqheight: dd 768
|
|
ebdaptr: dd 0
|
|
hw_stack: dd 0
|
|
bpb_sec: dd 0 ;ESP's first sector
|
|
root_sec: dd 0 ;root directory's first sector
|
|
data_sec: dd 0 ;first data sector
|
|
clu_sec: dd 0 ;sector per cluster
|
|
origcount: dw 0
|
|
cdromdev: db 0
|
|
bootdev: db 0
|
|
readdev: db 0
|
|
cntdev: db 0
|
|
hasinitrd: db 0
|
|
hasconfig: db 0
|
|
iscdrom: db 0
|
|
nosmp: db 0
|
|
bad_madt:
|
|
ap_done: dw 0
|
|
bsp_done: db 0 ;flag to indicate APs can run
|
|
fattype: db 0
|
|
bkp: dd ' '
|
|
if BBDEBUG eq 1
|
|
dbg_cpu db " * Detecting CPU",10,13,0
|
|
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_serial db " * Initrd over serial",10,13,0
|
|
dbg_gpt db " * Reading GPT",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
|
|
dbg_scan db " * Autodetecting kernel",10,13,0
|
|
dbg_elf db " * Parsing ELF64",10,13,0
|
|
dbg_pe db " * Parsing PE32+",10,13,0
|
|
dbg_smp db " * SMP numcores ",0
|
|
dbg_madt db " (bad MADT)",0
|
|
dbg_vesa db " * Screen VESA VBE",10,13,0
|
|
end if
|
|
backup: db " * Backup initrd",10,13,0
|
|
passphrase: db " * Passphrase? ",0
|
|
decrypting: db 13," * Decrypting...",0
|
|
clrdecrypt: db 13," ",13,0
|
|
starting: db "Booting OS..."
|
|
crlf: db 10,13,0
|
|
panic: db "-PANIC: ",0
|
|
noarch: db "Hardware not supported",0
|
|
a20err: db "Failed to enable A20",0
|
|
memerr: db "E820 memory map not found",0
|
|
nogzmem: db "Inflating: "
|
|
noenmem: db "Not enough memory",0
|
|
noacpi: db "ACPI not found",0
|
|
nogpt: db "No GPT found",0
|
|
nopar: db "No boot partition",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
|
|
bigcore: db "Kernel is too big",0
|
|
novbe: db "VESA VBE error, no framebuffer",0
|
|
nogzip: db "Unable to uncompress",0
|
|
notcdsect: db "Not 2048 sector aligned",0
|
|
nocipher: db "Unsupported cipher",10,13,0
|
|
badpass: db 13,"BOOTBOOT-ERROR: Bad passphrase",10,13,0
|
|
cfgfile: db "sys/config",0,0,0
|
|
kernel: db "sys/core"
|
|
db (64-($-kernel)) dup 0
|
|
;-----------padding to be multiple of 512----------
|
|
db (511-($-loader+511) mod 512) dup 0
|
|
loader_end:
|
|
|
|
;-----------BIOS checksum------------
|
|
chksum = 0
|
|
repeat $-loader
|
|
load b byte from (loader+%-1)
|
|
chksum = (chksum + b) mod 100h
|
|
end repeat
|
|
store byte (100h-chksum) at (loader.checksum)
|
|
|
|
;-----------bss area-----------
|
|
entrypoint: dq ?
|
|
core_ptr: dd ?
|
|
core_len: dd ?
|
|
gpt_ptr: dd ?
|
|
gpt_num: dd ?
|
|
gpt_ent: dd ?
|
|
ncycles: dq ?
|
|
lapic_ptr: dd ?
|
|
lapic_ids:
|
|
tinf_bss_start:
|
|
d_end: dd ?
|
|
d_lzOff: dd ?
|
|
d_dict_ring:dd ?
|
|
d_dict_size:dd ?
|
|
d_dict_idx: dd ?
|
|
d_tag: db ?
|
|
d_bitcount: db ?
|
|
d_bfinal: db ?
|
|
d_curlen: dw ?
|
|
d_ltree:
|
|
d_ltree_table:
|
|
dw 16 dup ?
|
|
d_ltree_trans:
|
|
dw 288 dup ?
|
|
d_dtree:
|
|
d_dtree_table:
|
|
dw 16 dup ?
|
|
d_dtree_trans:
|
|
dw 288 dup ?
|
|
offs: dw 16 dup ?
|
|
num: dw ?
|
|
lengths: db 320 dup ?
|
|
hlit: dw ?
|
|
hdist: dw ?
|
|
hclen: dw ?
|
|
tinf_bss_end:
|
|
|
|
virtual at tinf_bss_start
|
|
pass: db 256 dup ?
|
|
sha_d: db 64 dup ?
|
|
sha_l: dd ?
|
|
sha_b: dd 2 dup ?
|
|
sha_s: dd 8 dup ?
|
|
_a: dd ?
|
|
_b: dd ?
|
|
_c: dd ?
|
|
_d: dd ?
|
|
_e: dd ?
|
|
_f: dd ?
|
|
_g: dd ?
|
|
_h: dd ?
|
|
t1: dd ?
|
|
t2: dd ?
|
|
_m: dd 64 dup ?
|
|
chk: db 32 dup ?
|
|
iv: db 32 dup ?
|
|
pl: dd ?
|
|
_i: dd ?
|
|
end virtual
|
|
|
|
;-----------bound check-------------
|
|
;fasm will generate an error if the code
|
|
;is bigger than it should be
|
|
db 07C00h-4096-($-loader) dup ?
|