mirror of
https://github.com/ksherlock/hfs-boot.git
synced 2024-12-22 06:29:20 +00:00
378 lines
5.4 KiB
Plaintext
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
|