hfs-boot/bootblock.aii
2021-07-17 21:24:28 -04:00

378 lines
5.4 KiB
Plaintext

;
; HFS boot. Boot block.
; This is stage 0 of the bootloader. It will find a file named
; '!' in the root directory of an HFS volume, load it, and execute it
; in full 16-bit mode, with a = prodos block call vector.
;
; this currently only works with 512-byte blocks (max volume size = 64M)
; but there's enough room to support variable block sizes.
include 'hfs.aii'
string asis
blanks on
; smartport doesn't currently work ($28 no drive error because the unit isn't setup correctly?)
__smartport__ set 0
zp record 0
slot ds.w 1
;vector ds.w 1
offset ds.w 1
bnum ds.w 1
count ds.w 1
extents ds.b 3*HFSExtentDescriptor.sizeof
endr
if __smartport__ then
sp record $20
ReadBlock equ $01
pcount ds.b 1
unit ds.b 1
buffer ds.w 1
block ds.l 1 ; actually 24-bit
endr
else
pro record $42
cmd ds.b 1
unit ds.b 1
buffer ds.b 2
block ds.b 2
endr
endif
data record $2000
ds.b 512
endr
entry read_block, read_block_abs, read_extent_block
entry vector
boot proc
longi off
longa off
with zp
dc.b $01 ; prodos boot id :D
if __smartport__ then
stx sp.unit
else
stx pro.unit
endif
txa
lsr a
lsr a
lsr a
lsr a
ora #$c0
sta vector+1
sta slot+1
stz slot
; check for prodos block-device signature bytes
; todo -- switch to extended smartport? needed for second stage.
; xx $20 xx $00 xx $03 [xx $00 - smarport ]
ldy #1
lda (slot),y
cmp #$20
bne noboot
ldy #3
lda (slot),y
bne noboot
ldy #5
lda (slot),y
cmp #$03
bne noboot
if __smartport__ then
ldy #7
lda (slot),y
bne noboot
; ,$fb = smartport id byte which indicates if extended. not needed (yet)
endif
ldy #$ff
lda (slot),y
if __smartport__ then
inc a
inc a
inc a
endif
sta vector
bra ok
; not a prodos/smartport device.
noboot brk $ea
ok
if __smartport__ then
lda #3
sta sp.pcount
else
lda #1 ; prodos read block
sta pro.cmd
endif
clc
xce
rep #$30
longi on
longa on
stz offset
stz bnum
stz count
lda #data
if __smartport__ then
sta sp.buffer
; stz sp.block ; will overwrite
stz sp.block+2
else
sta pro.buffer
endif
lda #2
jsr read_block_abs
;
; assumes 512-byte blocks (max size = 64MB)
;
; wait a minute... max 65535 blocks, therefore high word of allocation block, etc, always 0.
; i assume hfs use 32-bit links in the btree for in-memory use (24-bit or 32 pointers)
;
; search for a file named ! in the root directory.
; ! is ascii char $21 so it should sort early.
;
;
with HFSMasterDirectoryBlock
lda data+drAlBlSt
xba
sta offset
ldx #3*HFSExtentDescriptor.sizeof-2
@cloop lda data+drCTExtRec,x
xba
sta extents,x
dex
dex
bpl @cloop
endwith
; lda offset
; clc
; adc extents
lda extents
jsr read_block
;
; block should be a btree header block. find the first leaf node.
;
with BTHeaderRec
; lda data+BTNodeDescriptor.sizeof+firstLeafNode
; xba
; sta leaf+2
lda data+BTNodeDescriptor.sizeof+firstLeafNode+2
xba
; sta bnum
endwith
;
; assert leaf < # allocated lbocks?
;
;lda leaf
; s/b leaf + cat extent + offset; todo - this offset is in terms of the catalog extent
jsr read_extent_block
lda data+BTNodeDescriptor.numRecords ; # of records
beq advance
xba
sta count
again
ldx #512-2 ; last entry
@loop
lda data,x ; entry offset
xba
tay
lda data+HFSCatalogKey.parentID,y ; parent id
bne notfound
lda data+HFSCatalogKey.parentID+2,y
xba
cmp #2
blt @next
beq @name
bge notfound
@name ; name is a p-string.
lda data+HFSCatalogKey.nodeName,y
cmp #$2101 ; pstr !
beq found
bge notfound
@next dex
dex
dec count
bne @loop
advance ; next block!
lda data+BTNodeDescriptor.fLink+2
beq notfound
xba
jsr read_extent_block
bra again
notfound
brk $ea
found
; y = offset in block
;
; only works with contiguous files....
; first block?
; 8 is magic offset for a key named !
; assume < 65535 bytes :)
with HFSCatalogFile
lda data+8+recordType,y
and #$00ff
cmp #kHFSFileRecord
bne notfound
lda data+8+dataPhysicalSize+2,y
; xba
lsr a ; >>9 since already xba
and #%01111111
beq notfound
sta count
; todo -- all extents...
lda data+8+dataExtents,y
xba
sta extents
lda data+8+dataExtents+2,y
xba
sta extents+2
; now load the blocks and
lda #$2000
if __smartport__ then
sta sp.buffer
else
sta pro.buffer
endif
stz bnum
@loop
lda bnum
jsr read_extent_block
inc bnum
lda #512
clc
if __smartport__ then
adc sp.buffer
sta sp.buffer
else
adc pro.buffer
sta pro.buffer
endif
dec count
bne @loop
ldx slot
ldy vector
if __smartport__ then
lda sp.unit
else
lda pro.unit
endif
and #$00ff
jmp $2000 ; kiss of life.
endp
read_block proc
entry read_block_abs
entry vector
; input
; a = hfs block #
; will be adjusted for allocation block offset
;
with zp
clc
adc offset
read_block_abs
;
; based on testing, this drops into emulation mode, so do it and recover.
;
if __smartport__ then
sta sp.block
else
sta pro.block
endif
php
sec
xce
dc.b $20 ; jsr
vector dc.w $ffff
if __smartport__ then
dc.b sp.ReadBlock
dc.w sp
endif
bcs @fail
xce
plp
rts
@fail brk $ea
endp
read_extent_block proc
; a = block #
; This doesn't check beyond the 3rd extent
with zp,HFSExtentDescriptor
@0
cmp extents+0+blockCount
bcs @1
; clc
adc extents+0+startBlock
bra read_block
@1 sbc extents+0+blockCount
cmp extents+4+blockCount
bcs @2
; clc
adc extents+4+startBlock
bra read_block
@2 sbc extents+4+blockCount
cmp extents+8+blockCount
bcs @3
adc extents+8+startBlock
bra read_block
@3 brk $ea
endp
end