Autor Thema: Bootloader Problem  (Gelesen 6873 mal)

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« am: 18. April 2005, 15:59 »
Ich hab mich jetzt entschlossen große Teile bei meinem OS neu zu coden. Also hab ich mit dem Bootsector angefangen und den alten umgebaut, erweitert und besser strukturiert. Das Problem an der Sache ist das er jetzt nicht mehr die Datei findet die er laden soll. Ist eigentlich alles relativ simpel gehalten da die Hauptarbeit in stage2.sys abläuft, sollte also verständlich sein.

Wenn man ihn startet (auf normalen PC, bei Bochs ka), kommen alle Messages und er malt 14 Punkte (für jeden Sektor von Rootdir einen). Dann kommt ein File Error.

[BITS 16]
[ORG 0x7C00]

;------- BIOS Parameter Block und BS FAT12 --------
jmp short start
nop
%include "G:\_UnrealOS\source\boot\FAT.inc"

;---------------------MAIN CODE--------------------
start:

; BOOTLAUFWERK SPEICHERN---------------------------
mov [DriveNumber], dl ; Von DL in Var kopieren

; SEGMENTE UPDATEN---------------------------------
mov ax, cs ; Codesegment ermitteln
mov ds, ax ; und in alle anderen Segmente schreiben
mov es, ax
mov gs, ax
mov fs, ax

; VORRÜBERGEHENDEN STACK BAUEN---------------------
mov ax, 0x7B0 ; Stack Adresse ist 0x7BFF
mov ss, ax
mov sp, 0xF0

; BOOTMESSAGES ANZEIGEN----------------------------
mov si, MsgBoot ; BootMsg laden
call putstr ; und anzeigen
mov si, MsgLoading ; Loading Stage2 Message laden
call putstr ; und anzeigen

; ROOTDIR NACH 0x7E00 LADEN------------------------
; Die Zieladresse steht per Default schon richtig
; Startsektor steht auch schon richtig
mov cx, [RootSize] ; Anzahl der Sektoren laden
call ReadSectors ; Laden!

; ES UPDATEN---------------------------------------
mov bx, 0x7C00
mov es, bx

; STAGE2.SYS LADEN---------------------------------
Search:
mov cx, word [MaxRootEntries] ; Maximale Anzahl der Einträge
mov di, 0x200 ; Bei Sektor 2 starten
.1:
push cx ; CX sichern
mov cx, 11 ; CX <- 11 (Länge eines Dateinamens)
mov si, FileName ; Dateiname laden
push di ; DI sichern
rep cmpsb ; Zeichen für Zeichen verlgeichen (Zu suchender Dateiname & aktueller)
pop di ; DI wiederherstellen
je Found ; Gefunden? -> Dann springen!
pop cx ; Nein? -> CX wiederherstellen
add di, 32 ; Nächster Eintrag
loop .1 ; Weitermachen
jmp err ; Alle Einträge durchsucht und trotzdem kein Erfolg? -> Fehler!

Found:
mov ax, [di+26] ; Startsektor der Datei ermitteln und in AX schreiben
call fat2lsn ; FAT-Startsektor in echten LSN Sektor umrechnen
mov [FileStart], ax ; Startadresse fertig berechnet, deshalb speichern
mov ax, [di+28] ; Dateigröße in AX speichern
call bytes2sectors ; Dateigröße von Bytes in die Anzahl der Sektoren umrechnen
mov cx, ax ; und in CX speichern
mov ax, [FileStart] ; Startsektor der Datei in AX speichern
mov [LBA], ax ; Startsektor für ReadSectors festlegen
mov [LoaderSegment], word 0x840 ; Zielsegment
call ReadSectors ; Datei laden!
 
; ZU STAGE2.SYS SPRINGEN---------------------------
push word [DriveNumber] ; Bootlaufwerk pushen (wird von stage2.sys benötigt)
jmp 0x840:0x0 ; Zu stage2 springen

; SYSTEM ANHALTEN----------------------------------
jmp hang

;---------------------FUNCTIONS--------------------

; putstr
; Stringausgabe
; String steht in SI
putstr:
;pusha ; Alle Register sichern

.1
lodsb ; Byte laden
or al,al ; Kommt immer der alte Wert raus, nötig für jz
jz short .2 ; Byte ist '\0'? -> Dann Ende
mov ah,0x0E ; Funktionsnummer
mov bx,0x0007 ; Farbe
int 0x10 ; Bildschirmausgabe + Cursorbewegung
jmp .1 ; Nächstes Byte
.2:

;popa ; Alle Register wiederherstellen
ret

; hang
; System aufhängen
hang:
cli ; Keine Interrupts
jmp $ ; Aufhängen per Endlosschleife

; lsn2chs
; Rechnet die Adresse vom LSN ins CHS Format um
; Parameter:
; o AX = LSN
; Rückgabe:
; o CL = Sector
; o DH = Head
; o CH = Cylinder
lsn2chs:
xor dx, dx ; DX <- 0
mov bx, [SectorsPerTrack] ; BX <- Sektoren pro Track
div bx ; dx=(ax mod bx)+1
inc dx ; DX um eins erhöhen
push dx ; Wird der absolute Sektor sein
xor dx, dx ; DX <- 0
mov bx, [NumHeads] ; BX <- Anzahl Heads
div bx
mov ch, al ; Track
mov dh, dl ; Head
pop ax ; Sektor von Stack nach AX
mov cl, al ; Sektor in CL
ret

; ReadSectors
; Sektoren laden
; Parameter:
; o CX = # Sektoren
; o LBA = Ab welchem Sektor
ReadSectors:
mov ax, [LBA]

.1:
push cx ; CX sichern
call lsn2chs ; LSN in CHS umrechnen
.2
mov es, [LoaderSegment] ; Ziel-Segment aus Var holen
mov bx, [LoaderOffset] ; Ziel-Offset aus Variable kopieren
mov ax, 0x0201 ; Sektor Lesen-Befehl und 1 Sektor lesen
mov dl, [DriveNumber] ; Drive Number kopieren
int 0x13 ; BIOS-Befehl: Lesen
jc .2 ; Fehler? -> Nochmal!

add bx, [BytesPerSector] ; BX um Anzahl der Bytes pro Sektor erhöhen
mov [LoaderOffset], bx ; BX beeinhaltet jetzt das neue Offset

mov si, MsgDot ; Punkt malen
call putstr

mov ax, [LBA] ; Sektornummer laden, ...
inc ax ; erhöhen und ...
mov [LBA], ax ; wieder speichern

pop cx ; CX wieder vom Stack holen
loop .1 ; Nächster Sektor

mov [LoaderOffset], word 0 ; Ziel-Offset auf 0 setzen

mov dx, 0x3F2 ; Motor anhalten
mov al, 0x0C
out dx, al
ret

; bytes2sectors
; Rechnet die Bytes in die entsprechende Sektorzahl um
; Parameter:
; o AX = Bytes
; Rückgabe:
; o AX = Anzahl der Sektoren
bytes2sectors:
xor dx, dx ; DX <- 0
div word [BytesPerSector] ; Teilen durch Bytes pro Sektor
cmp dx, 0 ; Glatt aufgegangen?
je .1 ; Ja? -> Dann Ende!
inc ax ; Nein? -> Dann noch einen Sektor meht
.1
ret

; fat2lsn
; FAT-Start-Sektor einer Datei in echte LSN umrechnen
; Parameter:
; o AX = FAT-Sektor
; Rückgabe:
; o AX = LSN-Sektor
fat2lsn:
sub ax, 0x2 ; Fat-Sektor minus 2 rechnen
add ax, [DataStart] ; und plus dem Startsektor der Daten
ret

; err
; Fehlermeldung anzeigen und Sysem anhalten
err:
mov si, MsgError ; Fehlermeldung laden
call putstr ; Und anzeigen
jmp hang ; System anhalten

;-----------------VARS----------------------------
RootSize dw 14 ; Größe des RootDirs in Sektoren
DataStart dw 33 ; Startsektor der eigentlichen FAT Daten

LBA dw 19

LoaderSegment dw 0x7E0 ; Ziel-Segment für ReadSectors
LoaderOffset dw 0x0 ; Ziel-Offset für ReadSectors

FileStart dw 0
FileName db "STAGE2  SYS" ; Dateiname des 2nd Stage Loaders

MsgBoot db "UnrealOS Loader stage1",13,10,13,10,0
MsgLoading db "Loading stage2",0
MsgError db 13,10,"FILE ERROR!",13,10,0
MsgDot db '.',0

;-----------------BOOT----------------------------
times 510-($-$$) db 0
signature dw 0xAA55

Wenn jemand sonst noch Bugs findet kann er das natürlich auch sagen  :)

Thx DarkThing

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #1 am: 19. April 2005, 13:31 »
Umf... mit so nem fetten Stück code is das schwer was zu finden, wenn man nicht eingeweiht ist... Bau doch mal alles aus (oder markiers!) was sicher läuft, dann kann man sich die unsicheren oder unklaren stellen mal ansehen... sicher, dass die includes von FAT.inc RICHTIG gehen, also nicht da irgendwo der fehler ist?
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 19. April 2005, 15:49 »
Wenn bei Fat.inc ein Fehler wär würd Nasm es ja sagen. Und da steht eigentlich nur ein ganz normaler FAT12 Header drin. Ich poste mal die Stücke bei denen das Problem liegen könnte einzeln und gib mal nen Kommentar dazu ab:

1. Hier könnte ein Problem mit den Segmenten oder dem Stack sein

[BITS 16]
[ORG 0x7C00]

;------- BIOS Parameter Block und BS FAT12 --------
jmp short start
nop
%include "G:\_UnrealOS\source\boot\FAT.inc"

;---------------------MAIN CODE--------------------
start:

; BOOTLAUFWERK SPEICHERN---------------------------
mov [DriveNumber], dl   ; Von DL in Var kopieren

; SEGMENTE UPDATEN---------------------------------
mov ax, cs      ; Codesegment ermitteln
mov ds, ax      ; und in alle anderen Segmente schreiben
mov es, ax
mov gs, ax
mov fs, ax

; VORRÜBERGEHENDEN STACK BAUEN---------------------
mov ax, 0x7B0   ; Stack Adresse ist 0x7BFF
mov ss, ax
mov sp, 0xF0


2. Hier ist die Frage ob das ES Update nach dem ReadSectors okay ist:

; ROOTDIR NACH 0x7E00 LADEN------------------------
; Die Zieladresse steht per Default schon richtig
; Startsektor steht auch schon richtig
mov cx, [RootSize]      ; Anzahl der Sektoren laden
call ReadSectors      ; Laden!

; ES UPDATEN---------------------------------------
mov bx, 0x7C00
mov es, bx


3. Der Teil der die Datei sucht sollte eigentlich in Ordnung sein weil ich ihn  100x überptüft hab.

4. Die Funktionen sollten eigentlich auch funktionieren. Kritisch ist nur lsn2chs und ReadSectors:

; lsn2chs
; Rechnet die Adresse vom LSN ins CHS Format um
; Parameter:
;   o AX = LSN
; Rückgabe:
;   o CL = Sector
;    o DH = Head
;   o CH = Cylinder
lsn2chs:
   xor dx, dx               ; DX <- 0
   mov bx, [SectorsPerTrack]   ; BX <- Sektoren pro Track
   div bx                  ; dx=(ax mod bx)+1
   inc dx                  ; DX um eins erhöhen
   push dx                  ; Wird der absolute Sektor sein
   xor dx, dx               ; DX <- 0
   mov bx, [NumHeads]         ; BX <- Anzahl Heads
   div bx
   mov ch, al               ; Track
   mov dh, dl               ; Head
   pop ax                  ; Sektor von Stack nach AX
   mov cl, al               ; Sektor in CL
ret

; ReadSectors
; Sektoren laden
; Parameter:
;   o CX = # Sektoren
;   o LBA = Ab welchem Sektor
ReadSectors:
   mov ax, [LBA]
   
   .1:
   push cx                  ; CX sichern
   call lsn2chs            ; LSN in CHS umrechnen
   .2
   mov es, [LoaderSegment]      ; Ziel-Segment aus Var holen
   mov bx, [LoaderOffset]      ; Ziel-Offset aus Variable kopieren
   mov ax, 0x0201            ; Sektor Lesen-Befehl und 1 Sektor lesen
   mov dl, [DriveNumber]      ; Drive Number kopieren
   int 0x13               ; BIOS-Befehl: Lesen
   jc .2                  ; Fehler? -> Nochmal!
   
   add bx, [BytesPerSector]   ; BX um Anzahl der Bytes pro Sektor erhöhen
   mov [LoaderOffset], bx      ; BX beeinhaltet jetzt das neue Offset
   
   mov si, MsgDot            ; Punkt malen
   call putstr
   
   mov ax, [LBA]            ; Sektornummer laden, ...
   inc ax                  ; erhöhen und ...
   mov [LBA], ax            ; wieder speichern
   
   pop cx                  ; CX wieder vom Stack holen
   loop .1                  ; Nächster Sektor
   
   mov [LoaderOffset], word 0   ; Ziel-Offset auf 0 setzen
   
   mov dx, 0x3F2            ; Motor anhalten
   mov   al, 0x0C
   out dx, al
ret


Ansonsten noch ein paar allgemeine Sachen:
Nachdem der Stack gebaut wurde werden ein paar Messages angezeigt die aber unwichtig sind. Dann wird das Rootdir geladen. Die ReadSectors Funktion nimmt den Startsektor aus der Variable LBA und die Zieladresse aus LoaderSegment & LoaderOffset. Alle drei Vars haben am Anfang schon den richtigen Wert für das Root Directory. Pro gelesenem Sektor wird ein Punkt gemalt. Da wie schon gesagt am Ende 14 da stehen wird das RD komplett geladen.

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 20. April 2005, 18:18 »
Hat jemand wenigstens ne Vermutung? Könnte es wirklich an den Segmenten liegen? Wenn ihr wollt poste ich auch noch die alte Version, die ja funktioniert hat aber höllisch schlecht geschrieben ist.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 20. April 2005, 21:31 »
Bei 1.: Die Segmentregister müssen 0 sein, wegen dem org 0x7C00. mov ax, cs ist falsch

Zitat
2. Hier ist die Frage ob das ES Update nach dem ReadSectors okay ist:


ES=0x7C00 und DI=0x200, damit wird der kernel nach 0x0007C200 geladen was wohl nicht der sinn ist ...
Dieser Text wird unter jedem Beitrag angezeigt.

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #5 am: 21. April 2005, 13:33 »
@DarkThing: ich meine einen logischen fehler, keinen syntaktischen...
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 21. April 2005, 13:57 »
#1: Werd ich mal testen.
#2: Die Zieladresse steht in LoaderSegment und LoaderOffset. Und vor dem ReadSectors-Aufruf zum Laden der Datei steht: mov es, [LoaderSegment]. In ReadSectors wird das hier gemacht: mov es, [LoaderSegment]. Nach ReadSectors setze ich ES einfach wieder zurück.

[EDIT] Der Vollständigkeit halber noch FAT12.inc:

OEM_ID                db "UNREALOS"
BytesPerSector        dw 0x0200
SectorsPerCluster     db 0x01
ReservedSectors       dw 0x0001
TotalFATs             db 0x02
MaxRootEntries        dw 0x00E0
TotalSectorsSmall     dw 0x0B40
MediaDescriptor       db 0xF0
SectorsPerFAT         dw 0x0009
SectorsPerTrack       dw 0x0012
NumHeads              dw 0x0002
HiddenSectors         dd 0x00000000
TotalSectorsLarge     dd 0x00000000
DriveNumber           db 0x00
Flags                 db 0x00
Signature             db 0x29
SerialNumber          dd 0xFFFFFFFF
VolumeLabel           db "UNREALOS   "
FileSystem            db "FAT12   "

joachim_neu

  • Beiträge: 1 228
    • Profil anzeigen
    • http://www.joachim-neu.de
Gespeichert
« Antwort #7 am: 22. April 2005, 13:42 »
gut, da wird ja wohl wenig falsch sein ;) nur warum machste da noch ein "nop" vor das include? ich dachte man müsste nur den sprung machn.
http://www.joachim-neu.de | http://www.orbitalpirates.de | http://www.middleageworld.de

System: 256 RAM, GeForce 2 MX 400, AMD Athlon XP 1600+, Windows XP, 1x Diskette, 1x DVD-ROM, 1x CD-R(W) Brenner,...

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #8 am: 22. April 2005, 13:46 »
Das macht er vielleicht weil ein short-jmp nur 2 Byte gross ist, dort aber 3 Byte reserviert sind.^^ Short jumps haben eine geringere Reichweite (+-128 byte) als near-jumps brauchen also nicht so viel Speicher
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

DarkThing

  • Beiträge: 652
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 22. April 2005, 19:28 »
Eigentlich geht beides. Ein FAT12-Bootsector fängt offiziell immer mit EB 3C 90 an. Was in Assembler der Sprungebefehl und ein nop ist. Wenn man das nop weglässt steht da EB 3C 00 was genausogut geht.

@Segmente: Ich hab den ganzen Teil einfach mal weggelassen -> Gleiches Problem. Wenn ich überall 0 reinschreibe gehts auch nicht.

 

Einloggen