393 lines
9.3 KiB
ArmAsm
393 lines
9.3 KiB
ArmAsm
!******************************************************************************
|
||
*******************************************************************************
|
||
|
||
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
|
||
|
||
Standalone Module boot0.md.s (primary bootstrapper)
|
||
|
||
|
||
Bearbeiter: P. Hoge
|
||
Datum: 04/01/87 11:20:26
|
||
Version: 1.1
|
||
|
||
*******************************************************************************
|
||
|
||
boot0 disk fuer einen Systemstart von der Harddisk
|
||
(primary bootstrapper)
|
||
|
||
bei autonatischem boot bzw Eingabe von CR bei manuellem
|
||
boot nach der Meldung mit > wird das Programm boot
|
||
(secundary bootstrapper) von der Harddisk
|
||
(vom ersten Filesystem)
|
||
in den Speicher des U8000 Systems
|
||
(Segment 0, ab Adresse %8000) geladen.
|
||
Bei manuellem boot kann nach der Meldung mit > auch
|
||
ein anderer filename (pathname) eingegeben werden.
|
||
Es wird das Filesystem md(0,0) - nicht das root File-
|
||
system benutzt.
|
||
boot0 benutzt den U8000 Monitor.
|
||
|
||
*******************************************************************************
|
||
******************************************************************************!
|
||
|
||
|
||
|
||
boot0_md_s module
|
||
|
||
|
||
$SECTION boot0
|
||
|
||
|
||
constant
|
||
|
||
DISK_BUFFER := %FA00 !array [%200 byte]!
|
||
BLOCK_POINTER := %FC00 !array [%228 byte]!
|
||
PATH_NAME := %FE28 !n * 14 byte fuer pathname!
|
||
|
||
MOVE_ADR := %F800
|
||
LOAD_ADR := %8000
|
||
|
||
TTIN := %04
|
||
TTWR := %06
|
||
DISK := %1E
|
||
|
||
global
|
||
|
||
!*---------------------------------------------------------------------------*!
|
||
!*
|
||
* eigentliches Programm von 8000 auf F800 moven
|
||
*!
|
||
!*---------------------------------------------------------------------------*!
|
||
|
||
START procedure
|
||
entry
|
||
ld r2, #%5800 !nonsegmented Systemmode!
|
||
ldctl FCW, r2 !fcw setzen!
|
||
ldb rh2, #(MOVE_ADR shr 8)
|
||
ldar r1, MAIN !Quelladr!
|
||
ld r15, r2
|
||
ld r14, #(DISK_BUFFER - MOVE_ADR)
|
||
ldirb @r2, @r1, r14
|
||
jp @r15
|
||
end START
|
||
|
||
!Dieses Programm ist voll relativ!
|
||
!Es wird auf MOVE_ADR gemoved!
|
||
|
||
|
||
!*---------------------------------------------------------------------------*!
|
||
!*
|
||
* Main Procedure
|
||
* Eingabe filename (pathname) bei manuellem boot
|
||
* bzw Standardname fuer secundary boot bei automatischem boot
|
||
* Suchen des files in der directory (bzw den derectories)
|
||
* Laden ab 8000 hex, Segment 0
|
||
* Starten des Programms
|
||
*!
|
||
!*---------------------------------------------------------------------------*!
|
||
|
||
MAIN procedure
|
||
entry
|
||
pushl @r15, rr6 !Monitor Parameter retten!
|
||
pushl @r15, rr4
|
||
test r4 !0=automatischer Boot!
|
||
jr nz, MAIN_LOOP !manueller Boot r14 ist 0!
|
||
|
||
ldar r14, MSG_BOOT !autom.:boot Kommando laden!
|
||
MAIN_LOOP:
|
||
ldar r8, MSG_PROMPT
|
||
calr PRINT_MSG !Meldung zur Eingabeanforderung!
|
||
ld r10, #PATH_NAME
|
||
ld r11, r10 !r11 Anf adr Puffer!
|
||
MAIN3:
|
||
ld r12, r11 !r12 aktueller Puffer Pointer!
|
||
MAIN4:
|
||
calr GETA
|
||
cpb rl0, #%0A !lf = Ende der Eingabe!
|
||
jr z, MAIN6
|
||
cpb rl0, #'/' !Name fuer directory file!
|
||
jr z, MAIN5
|
||
|
||
ldb @r12, rl0 !Zeichen in Puffer!
|
||
inc r12, #%01 !Pointer inc!
|
||
jr MAIN4 !naechstes Zeichen!
|
||
|
||
MAIN5:
|
||
cp r12, r11 !1. eingegebenes Zeichen ?!
|
||
jr z, MAIN4 !name eingeben!
|
||
calr CLEAR !Namensfeld bis Ende mit 00 beschreiben!
|
||
jr MAIN3 !naechsten Namen eingeben!
|
||
|
||
MAIN6: !Ende der Eingabe!
|
||
calr CLEAR !Rest vom Namensfeld mit 00 fuellen!
|
||
clrb @r11 !erstes Zeichen vom naechsten Namensfeld = 0!
|
||
|
||
|
||
!directories nach file durchsuchen!
|
||
|
||
ldk r11, #%02 !inumber der root directory!
|
||
MAIN7:
|
||
calr READ_INODE !inode lesen!
|
||
jr nz, MAIN16 !Disk Error!
|
||
testb @r10 !<> 0 directory einlesen!
|
||
!0 = gewuenschten file einlesen!
|
||
jr z, MAIN11 !Sprung Procedure file einlesen!
|
||
MAIN8:
|
||
!directory lesen!
|
||
test r13 !directory ende ?!
|
||
jr z, MAIN14 !Ja, file nicht gefunden!
|
||
calr READ_BLOCK !naechsten Block der directory einlesen!
|
||
jr nz, MAIN16 !Disk Error!
|
||
MAIN9:
|
||
pop r11, @r9 !inumber in directory!
|
||
test r11 !0=keine Datei auf diesem Platz eingetragen!
|
||
jr z, MAIN10 !naechster Platz in directory!
|
||
!Abstand 10 Hex Bytes 2 byte inumber 14 byte Name!
|
||
ldk r0, #14 !Laenge filename!
|
||
ld r1, r9
|
||
ld r2, r10 !filename in directory Block suchen!
|
||
cpsirb @r10, @r1, r0, nz
|
||
jr nz, MAIN7 !Name gefunden!
|
||
!in r11 ist inumber fuer gesuchte file!
|
||
|
||
ld r10, r2
|
||
MAIN10:
|
||
inc r9, #14
|
||
cp r9, #DISK_BUFFER+%200 !Ende Disk Puffer!
|
||
jr ge, MAIN8 !Name nicht gefunden, naechsten Block lesen!
|
||
jr MAIN9 !nicht gefunden, weiter im gleichen Block suchen!
|
||
|
||
!Procedure file einlesen!
|
||
|
||
MAIN11:
|
||
test r13 !file leer ?!
|
||
jr z, MAIN14
|
||
calr READ_BLOCK !1. Block der file lesen!
|
||
jr nz, MAIN16 !Disk Error!
|
||
cp @r9, #%E707 !Magic Nr!
|
||
!=nonsegmented, executable!
|
||
jr nz, MAIN14 !Fehler falsche Magic!
|
||
ld r11, %10(r9) !Entry Point des Programms!
|
||
ld r0, #%18 !size header!
|
||
add r0, %0A(r9) !size segment table!
|
||
add r9, r0 !Anfangsadr Programmcode!
|
||
ld r10, #LOAD_ADR !Ladeadr im Segment 0!
|
||
neg r0
|
||
add r0, #%200 !%200-header-segtable!
|
||
MAIN12:
|
||
ldirb @r10, @r9, r0 !Move Puffer auf echte Adr!
|
||
test r13 !noch Datenbloecke einzulesen ?!
|
||
jr z, MAIN13 !file eingelesen!
|
||
calr READ_BLOCK !alle weiteren Bloecke lesen!
|
||
jr nz, MAIN16 !Disk Error!
|
||
ld r0, #%0200 !RL!
|
||
jr MAIN12
|
||
|
||
!Programm starten!
|
||
|
||
MAIN13:
|
||
ld r15, #MOVE_ADR - 8 !Stackpointer fuer Parameter neu setzen!
|
||
popl rr4, @r15 !Rueckladen der Monitor Parameter!
|
||
popl rr6, @r15
|
||
jp @r11 !Sprung zum geladenen Programm!
|
||
|
||
|
||
|
||
!Fehlerbehandlung!
|
||
|
||
MAIN14:
|
||
ldar r8, MSG_ERROR
|
||
MAIN15:
|
||
calr PRINT_MSG
|
||
ldk r14, #0 !manuel boot setzen!
|
||
jr MAIN_LOOP
|
||
|
||
MAIN16: ldar r8, MSG_DERROR
|
||
jr MAIN15
|
||
end MAIN
|
||
|
||
internal
|
||
|
||
!*---------------------------------------------------------------------------*!
|
||
!*
|
||
* Inode Block fuer vorgegebene inumber lesen
|
||
* richtige inode ermitteln
|
||
*!
|
||
!*---------------------------------------------------------------------------*!
|
||
|
||
READ_INODE procedure
|
||
entry
|
||
inc r11, #%0F !aus inumber inode Block berechnen!
|
||
ld r5, r11
|
||
srl r5, #%03 !/8 ;8 inodes je Block!
|
||
xor r4, r4
|
||
calr READ_DISK !inode Block in DISK_BUFFER lesen!
|
||
ret nz !Disk Error!
|
||
and r11, #%07
|
||
sll r11, #%06
|
||
add r11, #DISK_BUFFER+8
|
||
popl rr12, @r11 !Laenge file aus inode!
|
||
addl rr12, #%01FF
|
||
srll rr12, #9 !in r13 nun Anzahl Bloecke der file!
|
||
ld r12, #BLOCK_POINTER
|
||
ld r9, r12 !array der Blockpointer!
|
||
ldk r1, #10 !10 direkte Pointer!
|
||
READ_INODE1:
|
||
clrb @r9 !direkte Pointer einlesen!
|
||
inc r9, #%01
|
||
ldk r0, #%03
|
||
ldirb @r9, @r11, r0 !move in Pointer array!
|
||
dec r1, #%01
|
||
jr nz, READ_INODE1
|
||
|
||
cp r13, #%0A !file < 10 Bloecke ?!
|
||
jr le, READ_INODE2 !ja=fertig!
|
||
|
||
xorb rh4, rh4 !Pointer zu einfach indirekt laden!
|
||
ldb rl4, @r11
|
||
inc r11, #%01
|
||
ldb rh5, @r11
|
||
inc r11, #%01
|
||
ldb rl5, @r11
|
||
calr READ_DISK !einfach indirekt Pointer Block lesen!
|
||
ret nz !Disk Error!
|
||
ld r1, #DISK_BUFFER
|
||
ld r0, #%0200 !RL!
|
||
ldirb @r9, @r1, r0 !in Pointerarray an die 10 direkten Pointer moven!
|
||
READ_INODE2:
|
||
setflg z
|
||
ret
|
||
end READ_INODE
|
||
|
||
!*---------------------------------------------------------------------------*!
|
||
!*
|
||
* 1 Block von Disk einlesen
|
||
*!
|
||
!*---------------------------------------------------------------------------*!
|
||
|
||
READ_BLOCK procedure
|
||
entry
|
||
popl rr4, @r12 !naechste Blocknummer!
|
||
calr READ_DISK
|
||
ret nz !Disk Error!
|
||
ld r9, #DISK_BUFFER
|
||
dec r13, #%01 !Anzahl Bloecke dec!
|
||
setflg z
|
||
ret
|
||
end READ_BLOCK
|
||
|
||
!*---------------------------------------------------------------------------*!
|
||
!*
|
||
* Programme zur Ein- Ausgabe an Console und zur
|
||
* Aufbereitung der Eingaben
|
||
*!
|
||
!*---------------------------------------------------------------------------*!
|
||
|
||
CLEAR procedure
|
||
entry
|
||
inc r11, #%0E !Pointer auf nachstes Namensfeld im PATH_NAME Puffer!
|
||
CLEAR1:
|
||
cp r12, r11
|
||
ret ge
|
||
clrb @r12 !Rest vom alten Namensfeld mit 00 beschreiben!
|
||
inc r12, #%01
|
||
jr CLEAR1
|
||
end CLEAR
|
||
|
||
PRINT_MSG procedure
|
||
entry
|
||
ldb rl0, @r8
|
||
testb rl0 !Ausgabe bis 00!
|
||
ret z
|
||
calr PRINT_CHAR
|
||
inc r8, #%01
|
||
jr PRINT_MSG
|
||
end PRINT_MSG
|
||
|
||
SET_BOOT procedure
|
||
entry
|
||
ldar r14, MSG_BOOT
|
||
end SET_BOOT !laeuft in GETA weiter!
|
||
|
||
GETA procedure
|
||
entry
|
||
test r14
|
||
jr z, GETA1
|
||
ldb rl0, @r14 !Zeichen nicht ueber CON!
|
||
!sondern aus Message holen!
|
||
inc r14, #%01
|
||
jr GETA2
|
||
|
||
!Zeichen von CON holen!
|
||
|
||
GETA1:
|
||
sc #TTIN
|
||
ld r0, r3
|
||
GETA2:
|
||
resb rl0, #%07 !reset bit 7!
|
||
cpb rl0, #%0D
|
||
jr nz, PRINT_CHAR !Zeichen ausgeben!
|
||
ldk r0, #%0A !cr in lf!
|
||
end GETA !laueft in PRINT_CHAR weiter!
|
||
|
||
PRINT_CHAR procedure
|
||
entry
|
||
cpb rl0, #%0A !Zeichen = LF ?!
|
||
jr nz, PUTA !nein normal Ausgeben!
|
||
cp r12, r10 !r12=r10=kein Zeichen eingegeben!
|
||
jr z, SET_BOOT !Boot Kommando laden!
|
||
ldk r14, #%00 !Kommando ueber CON eingeben setzen!
|
||
ldk r0, #%0D !cr lf ausgeben!
|
||
calr PUTA
|
||
ldk r0, #%0A
|
||
end PRINT_CHAR
|
||
|
||
PUTA procedure
|
||
entry
|
||
sc #TTWR
|
||
ret
|
||
end PUTA
|
||
|
||
!*---------------------------------------------------------------------------*!
|
||
!*
|
||
* Lesen 1 Block von Disk in Puffer
|
||
* Es wird der Disktreiber im Monitor benutzt
|
||
*!
|
||
!*---------------------------------------------------------------------------*!
|
||
|
||
READ_DISK procedure
|
||
entry
|
||
ldk r8, #10 !retries!
|
||
LOOP:
|
||
dec r15, #6
|
||
ldm @r15, r8, #3
|
||
|
||
ldk r7, #1 !read!
|
||
ldk r6, #0 !drive 0!
|
||
!in rr4 Blocknummer!
|
||
ldk r8, #0 !obere 16 bit der pysischen RAM Adr!
|
||
lda r9, DISK_BUFFER !Ladeadr untere 16 bit!
|
||
ld r10, #%200 !Laenge!
|
||
sc #DISK
|
||
ldm r8, @r15, #3
|
||
inc r15, #6
|
||
test r2 !<> 0 ist Fehler!
|
||
ret z
|
||
|
||
djnz r8, LOOP !10 Versuche!
|
||
test r2 !z flag!
|
||
ret
|
||
end READ_DISK
|
||
|
||
|
||
|
||
|
||
internal
|
||
|
||
MSG_PROMPT array [* byte] := '> %00'
|
||
MSG_BOOT array [* byte] := 'boot%l'
|
||
MSG_ERROR array [* byte] := '?%l%00'
|
||
MSG_DERROR array [* byte] := 'DISK ERROR%l%00'
|
||
|
||
end boot0_md_s
|