325 lines
6.6 KiB
NASM
325 lines
6.6 KiB
NASM
; $Id: bootsect.asm 5001 2012-10-12 11:34:05Z os $
|
|
|
|
;******************************************************************************
|
|
;* Betriebssysteme *
|
|
;*----------------------------------------------------------------------------*
|
|
;* *
|
|
;* B O O T S E C T *
|
|
;* *
|
|
;*----------------------------------------------------------------------------*
|
|
;* Code fuer den Disketten-Bootblock des System-Images. Das BIOS laedt den *
|
|
;* ersten Block einer Diskette (den Bootblock) beim Starten des Rechner in *
|
|
;* den Hauptspeicher und fuehrt ihn aus. Der Programmcode des Bootblocks *
|
|
;* laedt nun das restliche System und fuehrt es aus. *
|
|
;******************************************************************************
|
|
|
|
;
|
|
; Konstanten
|
|
;
|
|
BIOSSEG equ 0x07c0 ; Hierher wird der Bootsector
|
|
; vom BIOS geladen
|
|
BOOTSEG equ 0x0060 ; Hierher verschiebt sich der
|
|
; Boot-Code
|
|
SETUPSEG equ 0x9000 ; Hierher laedt der Boot-Code den
|
|
; Setup-Code (max. 64K inkl. Stack)
|
|
SYSTEMSEG equ 0x1000 ; System-Code (max. 512K)
|
|
SECTORSZ equ 512 ; Groesse eines Sektors in Bytes
|
|
|
|
[SECTION .text]
|
|
|
|
;
|
|
; Boot-Code
|
|
;
|
|
bootsector:
|
|
jmp skip_data
|
|
|
|
;------------------------------------------------------------------------------
|
|
;
|
|
; Datenbereich, der von 'build' beim Erzeugen der Boot-Diskette
|
|
; gefuellt wird.
|
|
;
|
|
pad:
|
|
times 4+bootsector-$ db 0 ; Bytes zum Auffuellen, damit 'total_tracks' an einer
|
|
; geraden und tools/build.c bekannten Adresse liegt
|
|
total_tracks:
|
|
dw 0 ; Anzahl der Tracks der Diskette
|
|
total_heads:
|
|
dw 0 ; Anzahl der Seiten der Diskette
|
|
total_sectors:
|
|
dw 0 ; Anzahl der Sektoren pro Track
|
|
setup_sectors:
|
|
dw 0 ; Anzahl der Sektoren, die der Setup-Code einnimmt
|
|
system_sectors:
|
|
dw 0 ; Anzahl der Sektoren, die das System einnimmt
|
|
bootdevice:
|
|
db 0 ; BIOS Geraetecode: 00: Disk A, 01: Disk B, ..., 0x80 HD0, ...
|
|
curr_track:
|
|
db 0 ; Track, bei dem die Diskette/Partition beginnt
|
|
curr_head:
|
|
db 0 ; Head, bei dem die Diskette/Partition beginnt
|
|
curr_sector:
|
|
db 0 ; Sector, bei dem die Diskette/Partition beginnt
|
|
|
|
;-----------------------------------------------------------------------
|
|
|
|
;
|
|
; Kopieren des Bootsectors
|
|
;
|
|
skip_data:
|
|
mov bl,dl ; vom BIOS uebergebenes Boot-Device sichern
|
|
|
|
mov ax,BIOSSEG
|
|
mov ds,ax
|
|
xor si,si
|
|
mov ax,BOOTSEG
|
|
mov es,ax
|
|
xor di,di
|
|
mov cx,SECTORSZ/2
|
|
rep movsw
|
|
;
|
|
; Ausfuehrung durch die Kopie fortsetzen
|
|
;
|
|
jmp BOOTSEG:start
|
|
;
|
|
; Segmentregister initialisieren und Platz fuer den Stack schaffen
|
|
;
|
|
start:
|
|
mov ax,cs ; Daten-, Stack- und Codesegment sollen
|
|
mov ds,ax ; hierher zeigen.
|
|
mov ss,ax
|
|
mov sp,4*SECTORSZ ; Drei Sektoren als Stack freilassen
|
|
|
|
mov [bootdevice],bl ; zuvor gesichertes Boot-Device permanent ablegen
|
|
|
|
;
|
|
; Ausgabe einer Meldung mit Hilfe eines BIOS-Aufrufs
|
|
;
|
|
mov ah,0x03 ; Feststellen der Cursor-Position
|
|
xor bh,bh
|
|
int 0x10
|
|
|
|
mov cx,13
|
|
mov bx,0x0007 ; page 0, attribute 7 (normal)
|
|
mov ax,ds
|
|
mov es,ax
|
|
mov bp,bootmessage
|
|
mov ax,0x1301 ; Ausgabe des Textes, Cursor bewegen
|
|
int 0x10
|
|
;
|
|
; Nachladen des Setup-Codes und des Systems selbst.
|
|
;
|
|
xor ah,ah ; Reset des Disketten-/Plattencontrollers
|
|
mov dl,[bootdevice]
|
|
int 0x13
|
|
;
|
|
; Informationen ueber die Laufwerksgeometrie holen
|
|
;
|
|
hdd_probe:
|
|
mov dl,[bootdevice]
|
|
test dl,0x80
|
|
jz load_setup ; Floppy mit den Standardparametern laden
|
|
mov ah,0x8
|
|
int 0x13
|
|
jc load_setup ; CF bei Fehler gesetzt
|
|
mov [total_heads],dh
|
|
mov ax,cx ; CX sichern
|
|
and ax,0x3f
|
|
mov [total_sectors],ax
|
|
mov ax,cx
|
|
shr ax,6
|
|
mov [total_tracks],ax
|
|
|
|
;
|
|
; Weiterstellen der Disketten-/Plattenposition um 1 (Bootblock)
|
|
;
|
|
load_setup:
|
|
call step_disk
|
|
|
|
;
|
|
; Laden des Setup-Codes
|
|
;
|
|
mov word [curr_segment],SETUPSEG
|
|
mov word [curr_offset],0
|
|
mov ax,[setup_sectors]
|
|
call load
|
|
;
|
|
; Laden des Kernels
|
|
;
|
|
mov word [curr_segment],SYSTEMSEG
|
|
mov word [curr_offset],0
|
|
mov ax,[system_sectors]
|
|
call load
|
|
;
|
|
; Floppy wieder abschalten
|
|
;
|
|
call stop_floppy_motor
|
|
;
|
|
; Start des Setup-Codes
|
|
;
|
|
mov ax, [system_sectors] ; Speichere Anzahl an System-Sektoren in AX.
|
|
jmp SETUPSEG:0
|
|
|
|
;
|
|
; load
|
|
;
|
|
; Die 'ax' Sektoren von der Diskette in den Hauptspeicher. Die Position auf
|
|
; der Diskette muss vorher in curr_head/curr_track/curr_sector und die
|
|
; Position im Hauptspeicher in curr_segment/curr_offset stehen. Die Positionen
|
|
; werden entsprechend der geladenen Sektoren weitergestellt.
|
|
;
|
|
load:
|
|
mov [to_load],ax
|
|
l_next_part:
|
|
mov al,[curr_head]
|
|
mov [last_head],al
|
|
mov al,[curr_track]
|
|
mov [last_track],al
|
|
mov al,[curr_sector]
|
|
mov [last_sector],al
|
|
mov ax,[curr_segment]
|
|
mov [last_segment],ax
|
|
mov ax,[curr_offset]
|
|
mov [last_offset],ax
|
|
|
|
mov al,0
|
|
|
|
l_loop: call step
|
|
|
|
cmp byte [curr_sector],0x01
|
|
je l_now
|
|
cmp word [curr_offset],0x0000
|
|
je l_now
|
|
cmp al,[to_load]
|
|
jne l_loop
|
|
|
|
l_now:
|
|
push ax
|
|
mov dl,[bootdevice]
|
|
mov dh,[last_head]
|
|
mov ch,[last_track]
|
|
mov cl,[last_sector]
|
|
mov bx,[last_segment]
|
|
mov es,bx
|
|
mov bx,[last_offset]
|
|
mov ah,0x02 ; Funktionscode fuer 'Lesen'
|
|
int 0x13
|
|
pop ax
|
|
|
|
push ax
|
|
call print_dot
|
|
pop ax
|
|
|
|
mov ah,0
|
|
sub [to_load],ax
|
|
jne l_next_part
|
|
ret
|
|
|
|
;
|
|
; step
|
|
;
|
|
; Stellt die aktuelle Position im Hauptspeicher und auf der Diskette
|
|
; um einen Sektor (512 Byte) weiter.
|
|
;
|
|
step: add al,1
|
|
call step_disk
|
|
call step_memory
|
|
ret
|
|
|
|
step_disk:
|
|
mov bl,[curr_sector]
|
|
add bl,1
|
|
mov [curr_sector],bl
|
|
cmp bl,[total_sectors]
|
|
jle l_1
|
|
mov byte [curr_sector],1
|
|
|
|
mov bl,[curr_head]
|
|
add bl,1
|
|
mov [curr_head],bl
|
|
cmp bl,[total_heads]
|
|
jne l_1
|
|
mov byte [curr_head],0
|
|
|
|
mov bl,[curr_track]
|
|
add bl,1
|
|
mov [curr_track],bl
|
|
|
|
l_1: ret
|
|
|
|
step_memory:
|
|
mov bx,[curr_offset]
|
|
add bx,SECTORSZ
|
|
mov [curr_offset],bx
|
|
test bx,0xffff
|
|
jne l_2
|
|
mov bx,[curr_segment]
|
|
add bx,0x1000 ; 64 KByte weiterstellen
|
|
mov [curr_segment],bx
|
|
|
|
l_2 ret
|
|
|
|
;
|
|
; Ausgabe eines Stern ('*') mit Hilfe eines BIOS-Aufrufs
|
|
;
|
|
print_dot:
|
|
mov ah,0x03 ; Feststellen der Cursor-Position
|
|
xor bh,bh
|
|
int 0x10
|
|
|
|
mov cx,1
|
|
mov bx,0x0007 ; page 0, attribute 7 (normal)
|
|
mov ax,ds
|
|
mov es,ax
|
|
mov bp,dot
|
|
mov ax,0x1301 ; Ausgabe des Textes, Cursor bewegen
|
|
int 0x10
|
|
|
|
ret
|
|
|
|
;
|
|
; stop_floppy_motor
|
|
;
|
|
; Stopt den Motor der Floppy, da das BIOS dazu in Kuerze nicht mehr in
|
|
; der Lage sein wird. Egal, ob von Floppy oder Platte gebootet wurde.
|
|
;
|
|
stop_floppy_motor:
|
|
mov dx,0x3f2
|
|
xor al,al
|
|
out dx,al
|
|
ret
|
|
|
|
;
|
|
; Datenbereich
|
|
;
|
|
|
|
bootmessage:
|
|
db 13,10
|
|
db 'booting ... '
|
|
|
|
dot:
|
|
db '*'
|
|
|
|
to_load:
|
|
dw 0
|
|
curr_segment:
|
|
dw 0
|
|
curr_offset:
|
|
dw 0
|
|
|
|
last_head:
|
|
db 0
|
|
last_track:
|
|
db 0
|
|
last_sector:
|
|
db 0
|
|
last_segment:
|
|
dw 0
|
|
last_offset:
|
|
dw 0
|
|
|
|
unused:
|
|
times bootsector+510-$ db 0
|
|
|
|
mark:
|
|
dw 0xaa55
|