kernel/test/ldosboot/fdkernpl.asm

247 lines
5.0 KiB
NASM

%if 0
Loader adjustment to load FreeDOS kernel
by C. Masloch, 2017
Usage of the works is permitted provided that this
instrument is retained with the works, so that any entity
that uses the works is notified of this instrument.
DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
%endif
%include "lmacros3.mac"
struc BS
bsJump: resb 3
bsOEM: resb 8
bsBPB:
endstruc
struc EBPB ; BPB sec
bpbBytesPerSector: resw 1 ; offset 00h 0Bh
bpbSectorsPerCluster: resb 1 ; offset 02h 0Dh
bpbReservedSectors: resw 1 ; offset 03h 0Eh
bpbNumFATs: resb 1 ; offset 05h 10h
bpbNumRootDirEnts: resw 1 ; offset 06h 11h -- 0 for FAT32
bpbTotalSectors: resw 1 ; offset 08h 13h
bpbMediaID: resb 1 ; offset 0Ah 15h
bpbSectorsPerFAT: resw 1 ; offset 0Bh 16h -- 0 for FAT32
bpbCHSSectors: resw 1 ; offset 0Dh 18h
bpbCHSHeads: resw 1 ; offset 0Fh 1Ah
bpbHiddenSectors: resd 1 ; offset 11h 1Ch
bpbTotalSectorsLarge: resd 1 ; offset 15h 20h
bpbNew: ; offset 19h 24h
ebpbSectorsPerFATLarge: resd 1 ; offset 19h 24h
ebpbFSFlags: resw 1 ; offset 1Dh 28h
ebpbFSVersion: resw 1 ; offset 1Fh 2Ah
ebpbRootCluster: resd 1 ; offset 21h 2Ch
ebpbFSINFOSector: resw 1 ; offset 25h 30h
ebpbBackupSector: resw 1 ; offset 27h 32h
ebpbReserved: resb 12 ; offset 29h 34h
ebpbNew: ; offset 35h 40h
endstruc
struc BPBN ; ofs B16 S16 B32 S32
bpbnBootUnit: resb 1 ; 00h 19h 24h 35h 40h
resb 1 ; 01h 1Ah 25h 36h 41h
bpbnExtBPBSignature: resb 1 ; 02h 1Bh 26h 37h 42h -- 29h for valid BPBN
bpbnSerialNumber: resd 1 ; 03h 1Ch 27h 38h 43h
bpbnVolumeLabel: resb 11 ; 07h 20h 2Bh 3Ch 47h
bpbnFilesystemID: resb 8 ; 12h 2Bh 36h 47h 52h
endstruc ; 1Ah 33h 3Eh 4Fh 5Ah
%ifndef _MAP
%elifempty _MAP
%else ; defined non-empty, str or non-str
[map all _MAP]
%endif
strdef PAYLOAD_FILE, "KERNEL.SYS"
struc LOADSTACKVARS, -10h
lsvFirstCluster: resd 1
lsvFATSector: resd 1
lsvFATSeg: resw 1
lsvLoadSeg: resw 1
lsvDataStart: resd 1
endstruc
lsvclSignature equ "CL"
lsvclBufferLength equ 256
struc LOADDATA, LOADSTACKVARS - 10h
ldMemoryTop: resw 1
ldLoadTop: resw 1
ldSectorSeg: resw 1
ldFATType: resb 1
ldHasLBA: resb 1
ldClusterSize: resw 1
ldParaPerSector:resw 1
ldLoadingSeg: ; word
lsvCommandLine: ; word
.start: equ $ - lsvclBufferLength
.signature: resw 1
ldLoadUntilSeg: ; word
lsvExtra: ; word
.partition: resb 1 ; byte
.flags: resb 1 ; byte
endstruc
lsvefNoDataStart equ 1
lsvefPartitionNumber equ 2
struc LOADCMDLINE, LOADDATA - lsvclBufferLength
ldCommandLine:
.start: resb lsvclBufferLength
endstruc
cpu 8086
org 0
addsection ENTRY, start=0 vstart=0
entry:
mov ax, cs
add ax, entry_size_p + payload_size_p
xor bx, bx
push ax
push bx
retf
align 16
endarea entry
addsection PAYLOAD, follows=ENTRY
payload:
realpayload:
incbin _PAYLOAD_FILE
align 16, db 38
endarea realpayload
addsection STACKRELOCATE, follows=PAYLOAD vstart=0
stackrelocate:
mov ax, 60h + payload_size_p
mov es, ax
xor di, di
xor si, si
lea cx, [ bp + 512 ]
rep movsb
mov ds, ax
mov si, bp
xor di, di
cmp word [ds:bp + ldCommandLine], 0FF00h
je @F
lea si, [bp + ldCommandLine + lsvclBufferLength - 2]
lea di, [bp + lsvCommandLine.start + lsvclBufferLength - 2]
mov cx, words(lsvclBufferLength)
%if words(lsvclBufferLength) <= 20
%error AMD erratum 109 workaround needed
%endif
std
rep movsw
cld
lea si, [bp + lsvCommandLine.start]
mov di, lsvclSignature
@@:
cli
mov ss, ax
mov sp, si
mov word [bp + lsvCommandLine.signature], di
; Note that this access uses the new ss.
; Also note: If no command line is passed,
; si will equal bp. That means the word
; written here is technically below sp,
; that is it belongs to the unused stack.
; This does not cause any problems however.
; It hardens the next load stage against
; accidentally expecting a command line if
; it does not check the offsets properly.
sti
jmp 60h:0
align 16
endarea stackrelocate
payload_size equ realpayload_size + stackrelocate_size
endarea payload, 1
addsection RELOCATE, follows=STACKRELOCATE vstart=0
relocate:
mov bx, 1000h
mov ax, 60h
mov es, ax
mov cx, payload_size_p
mov ax, cs
sub ax, cx
mov ds, ax
xor si, si
xor di, di
mov ax, cx
cmp ax, bx
jbe @F
mov cx, bx
@@:
sub ax, cx
shl cx, 1
shl cx, 1
shl cx, 1
rep movsw
@@:
mov dx, es
add dx, bx
mov es, dx ; next segment
mov dx, ds
add dx, bx
mov ds, dx ; next segment
sub ax, bx ; = how much to relocate after this round
mov cx, 1000h << 3 ; in case another full 64 KiB to relocate
jae @F ; another full 64 KiB to relocate -->
add ax, bx ; restore
shl ax, 1
shl ax, 1
shl ax, 1 ; convert paragraphs to words
mov cx, ax ; that many words
xor ax, ax ; no more to relocate after this round
@@:
xor si, si
xor di, di
rep movsw ; relocate next chunk
test ax, ax ; another round needed?
jnz @BB ; yes -->
; ax = 0
mov dl, [bp + bsBPB + ebpbNew + bpbnBootUnit]
mov bl, dl
push ss
pop ds
cmp word [bp + bsBPB + bpbSectorsPerFAT], ax
je @F
push ss
pop es
lea si, [bp + bsBPB + ebpbNew]
lea di, [bp + bsBPB + bpbNew]
mov cx, (512 - bsBPB - bpbNew + 1) >> 1
rep movsw
@@:
jmp 60h + realpayload_size_p:0