snapshot: reading from disk without BIOS!!
Both LBA and CHS coordinates are now working for the primary disk on the primary bus. Failure modes I ran into: - ATA ports are 16-bit values. Using instructions with 8-bit immediates will yield strange results. (I had to debug this twice because I missed poll-ata-primary-bus-primary-drive-regular-status-word the first time around.) Mu's toolchain has been found out here. bootstrap has good errors but doesn't support the instructions I need in boot.subx. The self-hosted phases support the instructions but provide no error-checking. Might be worth starting to add error-checking as I encounter the need. In this case, a vote for validating metadata sizes even if we don't validate that instructions pass in the right metadata sizes. - Can't poll readiness first thing. Maybe we need to always select the drive first. - Reading 8-bit values from a 16-bit port (data port 0x1f0) returns garbage. Reading 32-bit values however works totally fine; go figure. (Maybe it won't work on real hardware?) https://forum.osdev.org/viewtopic.php?t=36415 - Passing in a 0 segment will never return data.
This commit is contained in:
parent
89db4ec100
commit
fba2146593
1
bochsrc
1
bochsrc
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
display_library: sdl2
|
display_library: sdl2
|
||||||
|
|
||||||
|
#ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
|
||||||
ata0-master: type=disk, path="disk.img", mode=flat, cylinders=20, heads=16, spt=63 # 10MB, 512 bytes per sector
|
ata0-master: type=disk, path="disk.img", mode=flat, cylinders=20, heads=16, spt=63 # 10MB, 512 bytes per sector
|
||||||
boot: disk
|
boot: disk
|
||||||
# PS/2 mouse requires black magic that I don't know how to explain.
|
# PS/2 mouse requires black magic that I don't know how to explain.
|
||||||
|
|
214
boot.subx
214
boot.subx
|
@ -914,5 +914,219 @@ Font:
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
# offset 1800 (address 0x9400)
|
# offset 1800 (address 0x9400)
|
||||||
|
== code 0x9400
|
||||||
|
|
||||||
|
# Use 28-bit PIO mode to transfer one sector from the primary drive on the
|
||||||
|
# primary bus.
|
||||||
|
# Inspired by https://colorforth.github.io/ide.html
|
||||||
|
#
|
||||||
|
# Resources:
|
||||||
|
# https://wiki.osdev.org/ATA_PIO_Mode
|
||||||
|
# https://forum.osdev.org/viewtopic.php?f=1&p=167798
|
||||||
|
# read-sector, according to https://www.scs.stanford.edu/11wi-cs140/pintos/specs/ata-3-std.pdf
|
||||||
|
read-a-sector:
|
||||||
|
# . prologue
|
||||||
|
55/push-ebp
|
||||||
|
89/<- %ebp 4/r32/esp
|
||||||
|
# . save registers
|
||||||
|
50/push-eax
|
||||||
|
52/push-edx
|
||||||
|
# check for floating bus
|
||||||
|
{
|
||||||
|
31/xor %eax 0/r32/eax
|
||||||
|
ba/copy-to-edx 0x1f7/imm32
|
||||||
|
ec/read-port-dx-into-al
|
||||||
|
81 7/subop/compare %eax 0xff/imm32
|
||||||
|
75/jump-if-!= break/disp8
|
||||||
|
(abort "primary bus has no drives")
|
||||||
|
}
|
||||||
|
# kick off read
|
||||||
|
(ata-drive-select 0xe0) # primary drive; 4 LSBs contain 4 upper bits of LBA (here 0)
|
||||||
|
#? (ata-drive-select 0xa0) # primary drive in CHS + head number
|
||||||
|
(ata-error 0)
|
||||||
|
(ata-sector-count 1)
|
||||||
|
(ata-lba 0 0 0) # lower 24 bits of LBA
|
||||||
|
#? (ata-cyl-sector 1 0 0)
|
||||||
|
(ata-command 0x20) # read sectors with retries
|
||||||
|
# poll for results
|
||||||
|
(poll-ata-primary-bus-primary-drive-regular-status-word)
|
||||||
|
# print out results
|
||||||
|
ba/copy-to-edx 0x1f0/imm32
|
||||||
|
b9/copy-to-ecx 0x10/imm32
|
||||||
|
{
|
||||||
|
81 7/subop/compare %ecx 0/imm32
|
||||||
|
74/jump-if-= break/disp8
|
||||||
|
ed/read-port-dx-into-eax
|
||||||
|
(draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax)
|
||||||
|
(move-cursor-to-left-margin-of-next-line 0) # 0=screen
|
||||||
|
49/decrement-ecx
|
||||||
|
eb/jump loop/disp8
|
||||||
|
}
|
||||||
|
(abort "success")
|
||||||
|
$read-256-sectors:end:
|
||||||
|
# . restore registers
|
||||||
|
5a/pop-to-edx
|
||||||
|
58/pop-to-eax
|
||||||
|
# . epilogue
|
||||||
|
89/<- %esp 5/r32/ebp
|
||||||
|
5d/pop-to-ebp
|
||||||
|
c3/return
|
||||||
|
|
||||||
|
ata-drive-select: # n: byte
|
||||||
|
# . prologue
|
||||||
|
55/push-ebp
|
||||||
|
89/<- %ebp 4/r32/esp
|
||||||
|
# . save registers
|
||||||
|
50/push-eax
|
||||||
|
52/push-edx
|
||||||
|
#
|
||||||
|
8b/-> *(ebp+8) 0/r32/eax
|
||||||
|
ba/copy-to-edx 0x1f6/imm32
|
||||||
|
ee/write-al-into-port-dx
|
||||||
|
$ata-drive-select:end:
|
||||||
|
# . restore registers
|
||||||
|
5a/pop-to-edx
|
||||||
|
58/pop-to-eax
|
||||||
|
# . epilogue
|
||||||
|
89/<- %esp 5/r32/ebp
|
||||||
|
5d/pop-to-ebp
|
||||||
|
c3/return
|
||||||
|
|
||||||
|
ata-error: # n: byte
|
||||||
|
# . prologue
|
||||||
|
55/push-ebp
|
||||||
|
89/<- %ebp 4/r32/esp
|
||||||
|
# . save registers
|
||||||
|
50/push-eax
|
||||||
|
52/push-edx
|
||||||
|
#
|
||||||
|
8b/-> *(ebp+8) 0/r32/eax
|
||||||
|
ba/copy-to-edx 0x1f1/imm32
|
||||||
|
ee/write-al-into-port-dx
|
||||||
|
$ata-error:end:
|
||||||
|
# . restore registers
|
||||||
|
5a/pop-to-edx
|
||||||
|
58/pop-to-eax
|
||||||
|
# . epilogue
|
||||||
|
89/<- %esp 5/r32/ebp
|
||||||
|
5d/pop-to-ebp
|
||||||
|
c3/return
|
||||||
|
|
||||||
|
ata-sector-count: # n: byte
|
||||||
|
# . prologue
|
||||||
|
55/push-ebp
|
||||||
|
89/<- %ebp 4/r32/esp
|
||||||
|
# . save registers
|
||||||
|
50/push-eax
|
||||||
|
52/push-edx
|
||||||
|
#
|
||||||
|
8b/-> *(ebp+8) 0/r32/eax
|
||||||
|
ba/copy-to-edx 0x1f2/imm32
|
||||||
|
ee/write-al-into-port-dx
|
||||||
|
$ata-sector-count:end:
|
||||||
|
# . restore registers
|
||||||
|
5a/pop-to-edx
|
||||||
|
58/pop-to-eax
|
||||||
|
# . epilogue
|
||||||
|
89/<- %esp 5/r32/ebp
|
||||||
|
5d/pop-to-ebp
|
||||||
|
c3/return
|
||||||
|
|
||||||
|
ata-lba: # lo: byte, mid: byte, hi: byte
|
||||||
|
# . prologue
|
||||||
|
55/push-ebp
|
||||||
|
89/<- %ebp 4/r32/esp
|
||||||
|
# . save registers
|
||||||
|
50/push-eax
|
||||||
|
52/push-edx
|
||||||
|
# lo
|
||||||
|
8b/-> *(ebp+8) 0/r32/eax
|
||||||
|
ba/copy-to-edx 0x1f3/imm32
|
||||||
|
ee/write-al-into-port-dx
|
||||||
|
# mid
|
||||||
|
8b/-> *(ebp+0xc) 0/r32/eax
|
||||||
|
ba/copy-to-edx 0x1f4/imm32
|
||||||
|
ee/write-al-into-port-dx
|
||||||
|
# hi
|
||||||
|
8b/-> *(ebp+0x10) 0/r32/eax
|
||||||
|
ba/copy-to-edx 0x1f5/imm32
|
||||||
|
ee/write-al-into-port-dx
|
||||||
|
$ata-lba:end:
|
||||||
|
# . restore registers
|
||||||
|
5a/pop-to-edx
|
||||||
|
58/pop-to-eax
|
||||||
|
# . epilogue
|
||||||
|
89/<- %esp 5/r32/ebp
|
||||||
|
5d/pop-to-ebp
|
||||||
|
c3/return
|
||||||
|
|
||||||
|
# sector: [1, 63]
|
||||||
|
# cylinder: [0, 1023]
|
||||||
|
ata-cyl-sector: # sector: byte, cyl-lo: byte, cyl-hi: byte
|
||||||
|
# . prologue
|
||||||
|
55/push-ebp
|
||||||
|
89/<- %ebp 4/r32/esp
|
||||||
|
# . save registers
|
||||||
|
50/push-eax
|
||||||
|
52/push-edx
|
||||||
|
# sector
|
||||||
|
8b/-> *(ebp+8) 0/r32/eax
|
||||||
|
ba/copy-to-edx 0x1f3/imm32
|
||||||
|
ee/write-al-into-port-dx
|
||||||
|
# cyl-lo
|
||||||
|
8b/-> *(ebp+0xc) 0/r32/eax
|
||||||
|
ba/copy-to-edx 0x1f4/imm32
|
||||||
|
ee/write-al-into-port-dx
|
||||||
|
# cyl-hi
|
||||||
|
8b/-> *(ebp+0x10) 0/r32/eax
|
||||||
|
ba/copy-to-edx 0x1f5/imm32
|
||||||
|
ee/write-al-into-port-dx
|
||||||
|
$ata-lba:end:
|
||||||
|
# . restore registers
|
||||||
|
5a/pop-to-edx
|
||||||
|
58/pop-to-eax
|
||||||
|
# . epilogue
|
||||||
|
89/<- %esp 5/r32/ebp
|
||||||
|
5d/pop-to-ebp
|
||||||
|
c3/return
|
||||||
|
|
||||||
|
ata-command: # cmd: byte
|
||||||
|
# . prologue
|
||||||
|
55/push-ebp
|
||||||
|
89/<- %ebp 4/r32/esp
|
||||||
|
# . save registers
|
||||||
|
50/push-eax
|
||||||
|
52/push-edx
|
||||||
|
#
|
||||||
|
8b/-> *(ebp+8) 0/r32/eax
|
||||||
|
ba/copy-to-edx 0x1f7/imm32
|
||||||
|
ee/write-al-into-port-dx
|
||||||
|
$ata-command:end:
|
||||||
|
# . restore registers
|
||||||
|
5a/pop-to-edx
|
||||||
|
58/pop-to-eax
|
||||||
|
# . epilogue
|
||||||
|
89/<- %esp 5/r32/ebp
|
||||||
|
5d/pop-to-ebp
|
||||||
|
c3/return
|
||||||
|
|
||||||
|
poll-ata-primary-bus-primary-drive-regular-status-word:
|
||||||
|
# . save registers
|
||||||
|
50/push-eax
|
||||||
|
52/push-edx
|
||||||
|
{
|
||||||
|
ba/copy-to-edx 0x1f7/imm32
|
||||||
|
ec/read-port-dx-into-al
|
||||||
|
a8/test-bits-in-al 0x80/imm8/bsy # set zf if bit 7 (most significant) is not set
|
||||||
|
75/jump-if-zf-not-set-and-bit-7-set loop/disp8
|
||||||
|
a8/test-bits-in-al 8/imm8/drq # set zf if bit 3 is not set
|
||||||
|
74/jump-if-zf-set-and-bit-3-not-set loop/disp8
|
||||||
|
}
|
||||||
|
$poll-ata-primary-bus-primary-drive-regular-status-word:end:
|
||||||
|
# . restore registers
|
||||||
|
5a/pop-to-edx
|
||||||
|
58/pop-to-eax
|
||||||
|
# . epilogue
|
||||||
|
c3/return
|
||||||
|
|
||||||
# vim:ft=subx
|
# vim:ft=subx
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
Entry:
|
Entry:
|
||||||
# initialize stack
|
# initialize stack
|
||||||
bd/copy-to-ebp 0/imm32
|
bd/copy-to-ebp 0/imm32
|
||||||
|
(read-a-sector)
|
||||||
# always first run tests
|
# always first run tests
|
||||||
(run-tests)
|
(run-tests)
|
||||||
(num-test-failures) # => eax
|
(num-test-failures) # => eax
|
||||||
|
|
Loading…
Reference in New Issue