mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
419 lines
10 KiB
419 lines
10 KiB
;===============================================================================
|
|
; LOADER.ASM
|
|
;
|
|
; BOOTLOADER FOR ROMWBW PSYSTEM
|
|
;
|
|
; CP/M DISK FORMATS ALLOW FOR RESERVED TRACKS THAT CONTAIN AN IMAGE OF THE
|
|
; OPERATING SYSTEM TO BE LOADED WHEN THE DISK IS BOOTED. THE OPERATING SYSTEM
|
|
; IMAGE ITSELF IS NORMALLY PREFIXED BY A 1-N SECTORS CONTAINING OS BOOTSTRAP
|
|
; CODE AND DISK METADATA.
|
|
;
|
|
; THE RETROBREW COMPUTING GROUP HAS BEEN USING A CONVENTION OF PREFIXING THE
|
|
; OS IMAGE WITH 3 SECTORS (512 BYTES X 3 FOR A TOTAL OF 1536 BYTES):
|
|
;
|
|
; SECTOR 1: IBM-PC STYLE BOOT BLOCK CONTAINING BOOTSTRAP,
|
|
; PARTITION TABLE, AND BOOT SIGNATURE
|
|
; SECTOR 2: RESERVED
|
|
; SECTOR 3: METADATA
|
|
;
|
|
; THE HARDWARE BIOS IS EXPECTED TO READ AND LOAD THE FIRST TWO SECTORS FROM THE
|
|
; DISK TO MEMORY ADDRESS $8000 AND JUMP TO THAT LOCATION TO BEGIN THE BOOT
|
|
; PROCESS. THE BIOS IS EXPECTED TO VERIFY THAT A STANDARD BOOT SIGNATURE
|
|
; OF $55, $AA IS PRESENT AT OFFSET $1FE-$1FF. IF THE SIGNATURE IS NOT FOUND,
|
|
; THE BIOS SHOULD ASSUME THE DISK HAS NOT BEEN PROPERLY INITIALIZED AND SHOULD
|
|
; NOT JUMP TO THE LOAD ADDRESS.
|
|
;
|
|
;===============================================================================
|
|
;
|
|
#INCLUDE "../ver.inc"
|
|
;
|
|
#INCLUDE "psys.inc"
|
|
;
|
|
SYS_ENT .EQU $0100 ; SYSTEM (OS) ENTRY POINT ADDRESS
|
|
SYS_LOC .EQU $0100 ; STARTING ADDRESS TO LOAD SYSTEM IMAGE
|
|
SYS_END .EQU $0100 + loader_size + bios_size + boot_size ; ENDING ADDRESS OF SYSTEM IMAGE
|
|
;
|
|
SEC_SIZE .EQU 512 ; DISK SECTOR SIZE
|
|
BLK_SIZE .EQU 128 ; OS BLOCK/RECORD SIZE
|
|
;
|
|
PREFIX_SIZE .EQU (SEC_SIZE * 3) ; 3 SECTORS
|
|
;
|
|
META_SIZE .EQU 32 ; SEE BELOW
|
|
META_LOC .EQU (PREFIX_SIZE - META_SIZE)
|
|
;
|
|
PT_LOC .EQU $1BE
|
|
PT_SIZ .EQU $40
|
|
;
|
|
.ORG 0
|
|
;
|
|
;-------------------------------------------------------------------------------
|
|
; SECTOR 1
|
|
;
|
|
; THIS SECTOR FOLLOWS THE CONVENTIONS OF AN IBM-PC MBR CONTAINING THE OS
|
|
; BOOTSTRAP CODE, PARTITION TABLE, AND BOOT SIGNATURE
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
.FILL PT_LOC - $,0 ; FILL TO START OF PARTITION TABLE
|
|
;
|
|
; STANDARD IBM-PC PARTITION TABLE. ALTHOUGH A
|
|
; PARTITION TABLE IS NOT RELEVANT FOR A FLOPPY DISK, IT DOES NO HARM.
|
|
; THE CONTENTS OF THE PARTITION TABLE CAN BE MANAGED BY FDISK80.
|
|
;
|
|
; BELOW WE ALLOW FOR 32 SLICES OF ROMWBW CP/M FILESYSTEMS
|
|
; FOLLOWED BY A FAT16 PARTITION. THE SLICES FOLLOW THE ORIGINAL
|
|
; HD512 ROMWBW FORMAT. IF THE DISK IS USING HD1K, A SEPARATE
|
|
; PARTITION TABLE WILL BE IN PLACE AND RENDER THIS PARTITION TABLE
|
|
; IRRELEVANT.
|
|
;
|
|
; THE CYL/SEC FIELDS ENCODE CYLINDER AND SECTOR AS:
|
|
; CCCCCCCC:CCSSSSSS
|
|
; 76543210:98543210
|
|
;
|
|
PART0:
|
|
.DB 0 ; ACTIVE IF $80
|
|
.DB 0 ; CHS START ADDRESS (HEAD)
|
|
.DW 0 ; CHS START ADDRESS (CYL/SEC)
|
|
.DB 0 ; PART TYPE ID
|
|
.DB 0 ; CHS LAST ADDRESS (HEAD)
|
|
.DW 0 ; CHS LAST ADDRESS (CYL/SEC)
|
|
.DW 0,0 ; LBA FIRST (DWORD)
|
|
.DW 0,0 ; LBA COUNT (DWORD)
|
|
PART1:
|
|
.DB 0 ; ACTIVE IF $80
|
|
.DB 0 ; CHS START ADDRESS (HEAD)
|
|
.DW %1111111111000001 ; CHS START ADDRESS (CYL/SEC)
|
|
.DB 6 ; PART TYPE ID
|
|
.DB 15 ; CHS LAST ADDRESS (HEAD)
|
|
.DW %1111111111010000 ; CHS LAST ADDRESS (CYL/SEC)
|
|
.DW $4000,$0010 ; LBA FIRST (DWORD)
|
|
.DW $0000,$000C ; LBA COUNT (DWORD)
|
|
PART2:
|
|
.DB 0 ; ACTIVE IF $80
|
|
.DB 0 ; CHS START ADDRESS (HEAD)
|
|
.DW 0 ; CHS START ADDRESS (CYL/SEC)
|
|
.DB 0 ; PART TYPE ID
|
|
.DB 0 ; CHS LAST ADDRESS (HEAD)
|
|
.DW 0 ; CHS LAST ADDRESS (CYL/SEC)
|
|
.DW 0,0 ; LBA FIRST (DWORD)
|
|
.DW 0,0 ; LBA COUNT (DWORD)
|
|
PART3:
|
|
.DB 0 ; ACTIVE IF $80
|
|
.DB 0 ; CHS START ADDRESS (HEAD)
|
|
.DW 0 ; CHS START ADDRESS (CYL/SEC)
|
|
.DB 0 ; PART TYPE ID
|
|
.DB 0 ; CHS LAST ADDRESS (HEAD)
|
|
.DW 0 ; CHS LAST ADDRESS (CYL/SEC)
|
|
.DW 0,0 ; LBA FIRST (DWORD)
|
|
.DW 0,0 ; LBA COUNT (DWORD)
|
|
;
|
|
; THE END OF THE FIRST SECTOR MUST CONTAIN THE TWO BYTE BOOT SIGNATURE.
|
|
;
|
|
BOOTSIG .DB $55,$AA ; STANDARD BOOT SIGNATURE
|
|
;
|
|
;-------------------------------------------------------------------------------
|
|
; SECTOR 2
|
|
;
|
|
; THIS SECTOR HAS NOT BEEN DEFINED AND IS RESERVED.
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
.FILL SEC_SIZE,0 ; JUST FILL SECTOR WITH ZEROES
|
|
;
|
|
;-------------------------------------------------------------------------------
|
|
; SECTOR 3
|
|
;
|
|
; OS AND DISK METADATA
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
.FILL (BLK_SIZE * 3),0 ; FIRST 384 BYTES ARE NOT YET DEFINED
|
|
;
|
|
; THE FOLLOWING TWO BYTES ARE AN ADDITIONAL SIGNATURE THAT IS VERIFIED BY
|
|
; SOME HARDWARE BIOSES.
|
|
;
|
|
PR_SIG .DB $5A,$A5 ; SIGNATURE GOES HERE
|
|
;
|
|
.FILL (META_LOC - $),0
|
|
;
|
|
; METADATA
|
|
;
|
|
PR_WP .DB 0 ; (1) WRITE PROTECT BOOLEAN
|
|
PR_UPDSEQ .DW 0 ; (2) PREFIX UPDATE SEQUENCE NUMBER (DEPRECATED?)
|
|
PR_VER .DB RMJ,RMN,RUP,RTP ; (4) OS BUILD VERSION
|
|
PR_LABEL .DB "Unlabeled$$$$$$$","$" ; (17) DISK LABEL (EXACTLY 16 BYTES!!!)
|
|
.DW 0 ; (2) DEPRECATED
|
|
PR_LDLOC .DW SYS_LOC ; (2) ADDRESS TO START LOADING SYSTEM
|
|
PR_LDEND .DW SYS_END ; (2) ADDRESS TO STOP LOADING SYSTEM
|
|
PR_ENTRY .DW SYS_ENT ; (2) ADDRESS TO ENTER SYSTEM (OS)
|
|
;
|
|
#IF (META_SIZE != ($ - META_LOC))
|
|
.ECHO "META_SIZE VALUE IS WRONG!!!\r\n"
|
|
!!!
|
|
#ENDIF
|
|
;
|
|
#IF ($ != PREFIX_SIZE)
|
|
.ECHO "LOADER PREFIX IS WRONG SIZE!!!\r\n"
|
|
!!!
|
|
#ENDIF
|
|
;
|
|
;-------------------------------------------------------------------------------
|
|
; SECTOR 4+
|
|
;
|
|
; PSYSTEM LOADER
|
|
; - LOAD SBIOS TO HIGH MEMORY (JUST BELOW HBIOS PROXY)
|
|
; - LOAD PSYSTEM BOOTSTRAP & JUMP TO IT
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
;
|
|
#include "../HBIOS/hbios.inc"
|
|
;
|
|
;
|
|
bel .equ 7 ; ASCII bell
|
|
bs .equ 8 ; ASCII backspace
|
|
lf .equ 10 ; ASCII linefeed
|
|
cr .equ 13 ; ASCII carriage return
|
|
;
|
|
interp_base .equ $0100 ; first loc used by the interpreter
|
|
low_memory .equ $0100 ; lowest available ram location
|
|
interleave .equ 1 ; interleaving factor (n:1)
|
|
first_track .equ 1 ; first interleaved track
|
|
skew .equ 0 ; track-to-track skew
|
|
;
|
|
;
|
|
;
|
|
.org loader_loc
|
|
;
|
|
ld sp,stack ; setup private stack
|
|
;
|
|
call nl2 ; formatting
|
|
ld hl,str_banner ; display boot banner
|
|
call pstr ; do it
|
|
;
|
|
; Copy BIOS to running location
|
|
;
|
|
ld hl,loader_end ; BIOS image is at end of loader
|
|
ld de,bios_loc ; BIOS execution location
|
|
ld bc,bios_size ; Size of BIOS
|
|
ldir ; do it
|
|
;
|
|
; Copy p-System bootstrap to running location
|
|
;
|
|
ld hl,loader_end + bios_size ; bootstrap appended after BIOS
|
|
ld de,boot_loc ; bootstrap runs here
|
|
ld bc,boot_size ; size of bootstrap code
|
|
ldir ; do it
|
|
;
|
|
; Print some interesting info
|
|
;
|
|
call nl2 ; spacing
|
|
ld hl,str_info ; info string
|
|
call pstr ; print it
|
|
ld bc,bios_loc ; bios location adr
|
|
call prthexword ; print it
|
|
ld hl,str_info2 ; additional info string
|
|
call pstr ; print it
|
|
ld bc,boot_loc ; bootstrap location adr
|
|
call prthexword ; print it
|
|
;
|
|
; Push key values onto the stack
|
|
;
|
|
ld hl,seclen ; maximum number of bytes per sector
|
|
push hl
|
|
ld hl,sectors ; maximum number of sectors in table
|
|
push hl
|
|
ld hl,skew ; track-to-track skew
|
|
push hl
|
|
ld hl,first_track ; first interleaved track
|
|
push hl
|
|
ld hl,interleave ; interleaving factor
|
|
push hl
|
|
ld hl,seclen ; bytes per sector
|
|
push hl
|
|
ld hl,sectors ; sectors per track
|
|
push hl
|
|
ld hl,tracks ; tracks per disk
|
|
push hl
|
|
ld hl,bios_loc-2 ; top word of available ram - sbios address-2
|
|
push hl
|
|
ld hl,low_memory ; bottom word of available ram
|
|
push hl
|
|
ld hl,bios_loc ; address of BIOS (start of jump table)
|
|
push hl
|
|
ld hl,interp_base ; starting address of the interpreter
|
|
push hl
|
|
#ifdef TESTBIOS
|
|
ld hl,disks-1 ; maximum (highest) disk drive number
|
|
push hl
|
|
#endif
|
|
;
|
|
jp boot_loc ; jump to bootloader
|
|
;
|
|
ret
|
|
;
|
|
;
|
|
; Print string at HL on console, null terminated
|
|
;
|
|
pstr:
|
|
ld a,(hl) ; get next character
|
|
or a ; set flags
|
|
inc hl ; bump pointer regardless
|
|
ret z ; done if null
|
|
call cout ; display character
|
|
jr pstr ; loop till done
|
|
;
|
|
; Print volume label string at HL, '$' terminated, 16 chars max
|
|
;
|
|
pvol:
|
|
ld b,16 ; init max char downcounter
|
|
pvol1:
|
|
ld a,(hl) ; get next character
|
|
cp '$' ; set flags
|
|
inc hl ; bump pointer regardless
|
|
ret z ; done if null
|
|
call cout ; display character
|
|
djnz pvol1 ; loop till done
|
|
ret ; hit max of 16 chars
|
|
;
|
|
; Start a newline on console (cr/lf)
|
|
;
|
|
nl2:
|
|
call nl ; double newline
|
|
nl:
|
|
ld a,cr ; cr
|
|
call cout ; send it
|
|
ld a,lf ; lf
|
|
jp cout ; send it and return
|
|
;
|
|
; Print a dot on console
|
|
;
|
|
pdot:
|
|
push af
|
|
ld a,'.'
|
|
call cout
|
|
pop af
|
|
ret
|
|
;
|
|
; Print the hex byte value in A
|
|
;
|
|
prthexbyte:
|
|
push af
|
|
push de
|
|
call hexascii
|
|
ld a,d
|
|
call cout
|
|
ld a,e
|
|
call cout
|
|
pop de
|
|
pop af
|
|
ret
|
|
;
|
|
; Print the hex word value in BC
|
|
;
|
|
prthexword:
|
|
push af
|
|
ld a,b
|
|
call prthexbyte
|
|
ld a,c
|
|
call prthexbyte
|
|
pop af
|
|
ret
|
|
;
|
|
; Convert binary value in A to ASCII hex characters in DE
|
|
;
|
|
hexascii:
|
|
ld d,a
|
|
call hexconv
|
|
ld e,a
|
|
ld a,d
|
|
rlca
|
|
rlca
|
|
rlca
|
|
rlca
|
|
call hexconv
|
|
ld d,a
|
|
ret
|
|
;
|
|
; Convert low nibble of A to ASCII hex
|
|
;
|
|
hexconv:
|
|
and 0Fh ; low nibble only
|
|
add a,90h
|
|
daa
|
|
adc a,40h
|
|
daa
|
|
ret
|
|
;
|
|
; Output character from A
|
|
;
|
|
cout:
|
|
; Save all incoming registers
|
|
push af
|
|
push bc
|
|
push de
|
|
push hl
|
|
;
|
|
; Output character to console via HBIOS
|
|
ld e,a ; output char to E
|
|
ld c,CIO_CONSOLE ; console unit to C
|
|
ld b,BF_CIOOUT ; HBIOS func: output char
|
|
rst 08 ; HBIOS outputs character
|
|
;
|
|
; Restore all registers
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
pop af
|
|
ret
|
|
;
|
|
; Input character to A
|
|
;
|
|
cin:
|
|
; Save incoming registers (AF is output)
|
|
push bc
|
|
push de
|
|
push hl
|
|
;
|
|
; Input character from console via hbios
|
|
ld c,CIO_CONSOLE ; console unit to c
|
|
ld b,BF_CIOIN ; HBIOS func: input char
|
|
rst 08 ; HBIOS reads character
|
|
ld a,e ; move character to A for return
|
|
;
|
|
; Restore registers (AF is output)
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
ret
|
|
;
|
|
; Return input status in A (0 = no char, != 0 char waiting)
|
|
;
|
|
cst:
|
|
; Save incoming registers (AF is output)
|
|
push bc
|
|
push de
|
|
push hl
|
|
;
|
|
; Get console input status via HBIOS
|
|
ld c,CIO_CONSOLE ; console unit to C
|
|
ld b,BF_CIOIST ; HBIOS func: input status
|
|
rst 08 ; HBIOS returns status in A
|
|
;
|
|
; Restore registers (AF is output)
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
ret
|
|
;
|
|
str_banner .db "RomWBW HBIOS p-System Loader v"
|
|
.db BIOSVER
|
|
.db 0
|
|
str_info .db "Loading pSystem BIOS @ 0x",0
|
|
str_info2 .db ", Bootstrap @ 0x",0
|
|
;
|
|
.fill 32,0
|
|
stack .equ $
|
|
;
|
|
.fill loader_end - $
|
|
;
|
|
.end
|
|
|