i am workin on a 2nd stage loader. it have nothing
else to do then to load the kernel in the memory
above the 1mb mark. Its just looking up for the
"SYSTEM" folder and then searches there for the
"KERNEL.BIN". Till now everything's allright.
But when it has found the kernel it should load
it sector by sector to the buffer und switch in
pmode and copy it to the exact position. but when
i try to load the first sektor of the kernel it causes
errors. everytime i emulate it with bochs says
somthin else.
![Arrow :arrow:](./images/smilies/icon_arrow.gif)
got anyone an idea??
thanks
Uni_Sol
heres my code:
Code: Select all
; ### DISCRIPTION ############################################################
; ###
; ### Version list
; ### ver 1.0:
; ### Sucht den Kernel auf einer FAT12 Diskette und lädt ihn in den
; ### Speicher. Wenn kein Kernel gefunden wird, wird eine Fehler-
; ### meldung ausgegeben.
; ### Überschreibt den Bootloader damit alles möglichts simpel gehalten
; ### werden kann.
; ### Der Osloader ist mit standard C-Calling geschrieben.
; ### Alle Segment- und Offsetadresse sind wie folgt: 0000:XXXX.
; ###
; ### written by Robert H.
; ### Copyright (c) 2007
; ###
; ### DISCRIPTION END ########################################################
; ### MACRO SECTION ##########################################################
%include "../PRJ/SRC/includes/macros.asm"
; ### MACRO SECTION END ######################################################
; ### COMPILER SECTION #######################################################
[ORG 0x0500]
[BITS 16]
[CPU 386]
; ### COMPILER SECTION END ###################################################
; ### CODE SECTION ###########################################################
cli
cld
; push dword 4000
; push dword 0xB8000
; push dword GUI
; call _memcpy
; add sp, 12
;
; hlt
mov cx, 1000
mov ax, 0xB800
mov es, ax
xor ax, ax
mov di, ax
mov eax, 0x07000700
rep stosd
push 0
push 0
call _gotoxy
add sp, 4
push MsgWellcome
call _write
add sp, 2
; --- Stack zurücksetzen -----------------------------------------------------
mov ax, 0x9000
mov ss, ax
mov sp, 0xFFFF
; --- A20 Gate aufmachen -----------------------------------------------------
A20Gate:
in al, 0x64
test al, 00000010b
jnz A20Gate ; Schleife bis Buffer leer
mov al, 0xD0
out 0x64, al ; schicke Lesebefehl
wait_1: in al, 0x64
test al, 00000001b
jz wait_1 ; warten
in al, 0x60
or al, 00000010b
mov bl, al ; sezte A20, speichern in BX
wait_2: in al, 0x64
test al, 00000010b
jnz wait_2 ; Schleife bis Buffer leer
mov al, 0xD1
out 0x64, al ; schicke Lesebefehl
wait_3: in al, 0x64
test al, 00000010b
jnz wait_3 ; Schleife bis Buffer leer
mov al, bl
out 0x60, al ; A20 an Controller senden
; --- Speichermap erstellen --------------------------------------------------
GetMem:
xor eax, eax
mov ds, ax
mov ah, 0xC7
mov si, BIOS_MEMORY_MAP
int 15h
jc GetMemErr
jmp GetMemNoErr
GetMemErr:
push MsgMemErr
call _write
add sp, 2
GetMemNoErr:
; --- GDT/IDT erstellen ------------------------------------------------------
GDT_IDT:
mov ax, 0xFFFF
mov fs, ax
mov di, 0x0010
mov [fs:di ], word 0x00 ; DESC_0
mov [fs:di+ 2], word 0x00
mov [fs:di+ 4], word 0x00
mov [fs:di+ 6], word 0x00
mov [fs:di+ 8], word 0xFFFF ; DESC_1 (CODE)
mov [fs:di+10], word 0x0000
mov [fs:di+12], byte 0x00
mov [fs:di+13], byte 0x9A
mov [fs:di+14], byte 0xCF
mov [fs:di+15], byte 0x00
mov [fs:di+16], word 0xFFFF ; DESC_2 (DATA)
mov [fs:di+18], word 0x0000
mov [fs:di+20], byte 0x00
mov [fs:di+21], byte 0x92
mov [fs:di+22], byte 0xCF
mov [fs:di+23], byte 0x00
mov [GDT_REGISTER ], word 0xFFFF
mov [GDT_REGISTER+2], dword 0x100000
mov [IDT_REGISTER ], word 0xFFFF
mov [IDT_REGISTER+2], dword 0x110000
sidt [OLD_IDT_REGISTER]
; --- FDD reseten ------------------------------------------------------------
push MsgLoading
call _write
add sp, 2
res_drive:
xor dx, dx
mov dl, [BOOT_DRIVE]
test dh, 0x20 ; test if drive supports 13h
jnz readerror
push ds
xor ax, ax
int 13h
pop ds
jc readerror ; Fehler
; --- FAT_ROOT einelsen ------------------------------------------------------
load_fat:
push word READ_BUFFER ; Speicher
push word 0x000E ; Länge
push word 0x0013 ; Start
call _lsn_read
add sp, 6
; --- Ordner "SYSTEM" suchen -------------------------------------------------
mov cx, FAT_RootEntCnt ; Anzahl der einträge im Root
mov ax, READ_BUFFER ; DS:SI => Verz. Name im
xor bx, bx ; Root
mov ds, bx ; ES:DI => Verz. Name aus
mov es, bx ; Variable
read_root_ent:
push cx
mov cl, DIR_NAME_SIZE
mov si, ax ; Name aus Root
mov di, DirName ; Name aus Variable
repe cmpsb
jz read_system_folder ; Verz gefunden, Datei suchen
add ax, DIR_ETNRY_SIZE
pop cx
loop read_root_ent
or cx, cx ; Verz. nicht gefunden
jz booterror
; --- Startektor für "SYSTEM" errechnen --------------------------------------
read_system_folder:
add si, 0x0F ; [DS:SI] => DIR_FstClusLo
mov ax, word [es:si]
mov word [FILE_START_SEC], ax
push MsgDirFound
call _write
add sp, 2
; --- Fat laden --------------------------------------------------------------
push READ_BUFFER
push FAT_FATSize
push FAT_ResvdSecCnt
call _lsn_read
add sp, 6
; --- Datei "KERNEL.BIN" in "SYSTEM" suchen ----------------------------------
mov byte [LAST_SEC], 0x00
read_next_sec:
mov ax, [FILE_START_SEC] ; FileSec laden
add ax, 0x1F ; 31 als ausgleich addieren
push ROOT_BUFFER ; RootDirSector vom
push 0x01 ; Verz. System einlesen
push ax ; FileSec
call _lsn_read
add sp, 6
mov ax, ROOT_BUFFER
mov cx, 0x10 ; pro Sektor 16 Einträge
read_system_ent:
push cx
mov cl, DIR_NAME_SIZE
mov si, ax ; Name aus Root
mov di, FileName ; Name aus Variable
repe cmpsb
jz read_file ; Datei gefunden -> Laden
add ax, DIR_ETNRY_SIZE
pop cx
loop read_system_ent
; mov al, byte [LAST_SEC] ; letzter Sektor?
; or al, al ; ja? -> kein Kernel
; jnz booterror
; --- Nächsten Sektor vom "SYSTEM"-Root laden --------------------------------
mov ax, word [FILE_START_SEC]
mov bx, 0x03
mul bx
mov bx, 0x02
xor dx, dx
div bx ; ax = offset dx = shifting
mov bx, READ_BUFFER
add bx, ax
mov ax, [ES:BX]
cmp dx, 0x01 ; dx=1 -> shr 4
je shift ; dx=0 -> AND 0x0FFF
and ax, 0x0FFF
jmp cont
shift: shr ax, 0x04
cont: cmp ax, 0x0FFF
jne next
mov byte [LAST_SEC], 0x01 ; OK - letzter Sektor.
jmp read_next_sec ; durchsuchen
next: mov word [FILE_START_SEC], ax ; store the new sector
jmp read_next_sec ; for the next loop
; --- Startektor für "KERNEL.BIN" errechnen ----------------------------------
read_file:
add si, 0x0F ; [DS:SI] => DIR_FstClusLo
mov ax, word [es:si]
mov word [FILE_START_SEC], ax
mov dword [SECTOR_COUNTER], 0x00
push MsgFileFound
call _write
add sp, 2
; --- Datei "KERNEL.BIN" laden -----------------------------------------------
read_next_file_sec:
mov ax, word [FILE_START_SEC] ; FileSec laden
add ax, 0x1F ; 31 als ausgleich addieren
;;;; !!!!!!!!! HERE !!!!!!!!!!
;;;; when it reaches INT 13 its over
;;;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
push KERNEL_BUFFER ; Sektor in Buffer laden
push 0x01
push ax ; Sektor
call _lsn_read
add sp, 6
; --- Protected Mode einschalten zum kopieren --------------------------------
call HALT
pusha
push sp
push ds
push cs
push ss
push es
push fs
push gs
lgdt [GDT_REGISTER]
lidt [IDT_REGISTER]
mov eax, cr0
or eax, 0000001b
mov cr0, eax
jmp dword CODE_DESC:pmode_jmp
[BITS 32]
pmode_jmp:
mov ax, DATA_DESC
mov ds, ax
mov es, ax
mov ss, ax
xor ax, ax
mov fs, ax
mov gs, ax
mov eax, dword [SECTOR_COUNTER] ; Wdh. laden
mov ebx, 0x0200
mul ebx
add eax, KERNEL_HIMEM ; akt. Position berechnen
push 0x0200
push eax
push KERNEL_BUFFER
call _memcpy32 ; Sektor verschieben
add esp, 12
mov eax, dword [SECTOR_COUNTER] ; Iterationsnr. sichern
inc eax
mov dword [SECTOR_COUNTER], eax
; --- Protected Mode ausschalten um nächsten Sektor zu laden -----------------
pushf
push eax
lidt [OLD_IDT_REGISTER]
mov ax, 32
mov ds, ax
mov es, ax
mov ss, ax
mov eax, cr0
and al, 0xFE
jmp 24:$+7
[BITS 16]
mov cr0, eax
jmp 0:$+5
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
pop eax
popfd
pop gs
pop fs
pop es
pop ss
pop cs
pop ds
pop sp
popa
; --- Nächsten Sektor berechnen ----------------------------------------------
mov ax, word [FILE_START_SEC]
mov bx, 0x03
mul bx
mov bx, 0x02
xor dx, dx
div bx ; ax = offset dx = shifting
mov bx, READ_BUFFER
add bx, ax
mov ax, [ES:BX]
cmp dx, 0x01 ; dx=1 -> shr 4
je shift ; dx=0 -> AND 0x0FFF
and ax, 0x0FFF
jmp cont
fshift: shr ax, 0x04
fcont: cmp ax, 0x0FFF ; OK Fertig
je execute ; Kernelsprung vorbereiten
mov word [FILE_START_SEC], ax ; store the new sector
jmp read_next_file_sec ; for the next loop
; --- Protected Mode einschalten ---------------------------------------------
execute:
push MsgFileFound
call _write
add sp, 2
pop cx ; prüfen ob cx = 0
or cx, cx ; ja? -> kein kernel gefunden
jnz execute_1
jmp booterror
execute_1:
lgdt [GDT_REGISTER]
lidt [IDT_REGISTER]
mov eax, cr0
or eax, 0000001b
mov cr0, eax
jmp dword CODE_DESC:exec_pm
[BITS 32]
exec_pm: mov ax, DATA_DESC
mov ds, ax
mov es, ax
mov ss, ax
xor ax, ax
mov fs, ax
mov gs, ax
mov esp, 0x0009FFFF ; stack zurücksetzten
jmp dword CODE_DESC:KERNEL_HIMEM ; zum kernel springen
; --- Fehler ausgeben (Real Mode) --------------------------------------------
[BITS 16]
booterror:
push MsgBootError
jmp writeerr
readerror:
push MsgReadError
writeerr:
call _write
add sp, 2
reboot: push MsgReboot
call _write
add sp, 2
xor ax, ax ; Reboot after keypress
int 0x16
db 0xEA
dw 0x0000
dw 0xFFFF
; ### CODE SECTION END #######################################################
; ### FUNCTIONS SECTION ######################################################
HALT: push MsgHalt
call _write
hlt
FUNCTIONS_SECTION:
; --- _write -----------------------------------------------------------------
; -[ Param0 = String ]
[BITS 16]
_write:
enter 0, 0
pusha
xor ax, ax
mov ds, ax
mov si, [Param0]
mov ah, 0x0E
mov bx, 0x0007
__write_1:
lodsb
test al, 0xFF ; al AND 0xFF but no storage
jz __write_2
int 10h
jmp __write_1
__write_2:
popa
leave
ret
; --- _write END -------------------------------------------------------------
; --- _gotoxy ----------------------------------------------------------------
; -[ Param0 = Y ] [2]
; -[ Param1 = X ] [1]
[BITS 16]
_gotoxy:
enter 0, 0
pusha
xor ax, ax
mov ah, 0x02
xor bx, bx
mov cx, [Param1]
mov dl, cl,
mov cx, [Param0]
mov dh, cl
int 10h
popa
leave
ret
; --- _gotoxy END ------------------------------------------------------------
; --- _lsn_read --------------------------------------------------------------
; -[ Param0 = LSN ] [3]
; -[ Param1 = nSectors ] [2]
; -[ Param2 = Buffer ] [1]
[BITS 16]
_lsn_read:
enter 0, 0
pusha
jmp __lsn_read_code
var0 db 0x00
var1 db 0x00
var2 db 0x00
__lsn_read_code:
mov ax, [Param0] ; LSN
xor dx, dx
mov bx, 0x12 ; sector =
div bx ; (LSN % 18)
inc dx ; + 1
mov byte [var2], dl ; var2 = sector
xor dx, dx
mov bx, 2 ; head = (LSN / 18) % 2
div bx
mov byte [var1], dl ; var1 = head
mov ax, [Param0] ; LSN wiederherstellen
mov bx, 0x24 ; cylinder = LSN / 36
xor dx, dx
div bx
mov byte [var0], al ; var0 = cylinder
; mov cx, 0x03 ; 3 Leseversuche
__lsn_read_err:
; or cx, cx
; jz readerror
; push cx
;push dot
;call _write
;add sp, 2
xor bx, bx ; ES:BX Buffer
mov es, bx
mov bx, [Param2]
mov ax, [Param1]
mov ah, 0x02
mov ch, byte [var0]
mov cl, byte [var2]
mov dl, [BOOT_DRIVE]
mov dh, byte [var1]
int 13h
; jnc __lsn_no_err
; pop cx
jc __lsn_read_err ; Fehler
__lsn_no_err:
popa
leave
ret
; --- _lsn_read END ----------------------------------------------------------
; --- _memcpy ----------------------------------------------------------------
; -[ Param0 = src ] [3]
; -[ Param1 = dest ] [2]
; -[ Param2 = count ] [1]
[BITS 16]
_memcpy:
enter 0, 0
pusha
mov esi, dword [Param320] ; Quelladresse nach ESI
mov edi, dword [Param321] ; Zieladresse nach EDI
mov ecx, dword [Param322] ; Anzahl Bytes nach ECX
mov edx, ecx ; ECX nach EDX kopieren
and ecx, 0xFFFFFFFC ; Ersten beiden Bits in ECX löschen
; Ergibt durch 4 teilbare Zahl
shr ecx, 2 ; ECX durch 4 dividieren
rep a32 movsd ; DWORDS kopieren
mov ecx, edx ; EDX wieder nach ECX kopieren
and ecx, 3 ; Alle Bits bis auf ersten beiden löschen
rep a32 movsb ; BYTES kopieren
popa
leave
ret
; --- _memcpy END ------------------------------------------------------------
; --- _memcpy32 --------------------------------------------------------------
; -[ Param0 = src ] [3]
; -[ Param1 = dest ] [2]
; -[ Param2 = count ] [1]
[BITS 32]
_memcpy32:
enter 0, 0
pusha
mov esi, [Param320] ; Quelladresse nach ESI
mov edi, [Param321] ; Zieladresse nach EDI
mov ecx, [Param322] ; Anzahl Bytes nach ECX
mov edx, ecx ; ECX nach EDX kopieren
and ecx, 0xFFFFFFFC ; Ersten beiden Bits in ECX löschen
; Ergibt durch 4 teilbare Zahl
shr ecx, 2 ; ECX durch 4 dividieren
rep movsd ; DWORDS kopieren
mov ecx, edx ; EDX wieder nach ECX kopieren
and ecx, 3 ; Alle Bits bis auf ersten beiden löschen
rep movsb ; BYTES kopieren
popa
leave
ret
; --- _memcpy32 END ----------------------------------------------------------
; ### FUNCTIONS SECTION END ##################################################
; ### DATA SECTION ###########################################################
[BITS 16]
DATA_SECTION:
DirName db "SYSTEM "
FileName db "KERNEL BIN"
MsgWellcome db "Bitte warten. Kernel wird initialisiert.",
db 13, 10, 0
MsgLoading db 13, 10, "Lade ", 0
MsgDirFound db "/SYSTEM/", 0
MsgFileFound db "KERNEL.BIN", 13 , 10, 0
MsgBootError db 13, 10, "Fehler: Es wurde kein Kernel gefunden.",
db 13, 10, 0
MsgReadError db 13, 10, "Fehler: Fehler beim Lesen vom Laufwerk",
db 13, 10, 0
MsgMemErr db 13, 10, "Fehler: Beim ermitteln des installierten RAMs",
db 13, 10, " ist ein fehler aufgetreten.",
db 13, 10, 0
MsgReboot db "Neustart mit Tastendruck", 0
db "SYSTEM ANGEHALTEN!", 13, 10, 0
PM_SWITCH db "PMODE_SWITCH ", 0
MsgHalt db "SYSTEM ANGEHALTEN!", 13, 10, 0
dot db 0xDB, 0
GUI db 0xC9,
times 78 db 0xCD
db 0xBB
db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
times 2 db 0xBA
times 78 db 0x20
db 0xBA
db 0xC8,
times 78 db 0xCD
db 0xBC, 0x00
; ### DATA SECTION END #######################################################