diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2021-03-27 17:47:23 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2021-03-27 17:50:44 -0700 |
commit | 7bf8adb893dcc524c7f1bc5e8f984385c9138d7d (patch) | |
tree | 7ae60840d8cb0356cee7a76cfd3c15bb5de4e58c /boot.subx | |
parent | 9818f1de981fe9206940cf89e9422388f8853cc2 (diff) | |
download | mu-7bf8adb893dcc524c7f1bc5e8f984385c9138d7d.tar.gz |
explicitly pass data disk to main
Diffstat (limited to 'boot.subx')
-rw-r--r-- | boot.subx | 395 |
1 files changed, 296 insertions, 99 deletions
diff --git a/boot.subx b/boot.subx index bc49b49d..8a4a5595 100644 --- a/boot.subx +++ b/boot.subx @@ -814,7 +814,42 @@ Font: # 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 -load-first-sector-from-primary-bus-secondary-drive: # out: (addr stream byte) +== data + +# We'll be gaining access just to the secondary drive on the primary bus for +# now. It will have the designated 'data' disk so we don't mess with the code +# disk. +# +# The type definition for this variable is in safe Mu (rather than unsafe +# SubX) code. +# All ports are 8-bit except data-port, which is 16-bit. +Primary-bus-secondary-drive: + # command-port: int (write) + 0x1f7/imm32 + # status-port: int (read) + 0x1f7/imm32 + # alternative-status-port: int (read) + 0x3f6/imm32 + # error-port: int (read) + 0x1f1/imm32 + # drive-and-head-port: int + 0x1f6/imm32 + # sector-count-port: int + 0x1f2/imm32 + # lba-low-port: int + 0x1f3/imm32 + # lba-mid-port: int + 0x1f4/imm32 + # lba-high-port: int + 0x1f5/imm32 + # data-port: int + 0x1f0/imm32 + # drive-code: byte # only drive-specific field + 0xf0/imm32 # LBA mode also enabled + +== code + +load-sector: # disk: (addr disk), lba: int, out: (addr stream byte) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -823,35 +858,46 @@ load-first-sector-from-primary-bus-secondary-drive: # out: (addr stream byte) 51/push-ecx 52/push-edx # check for drive - (secondary-drive-exists?) # => eax + (drive-exists? *(ebp+8)) # => eax 3d/compare-eax-and 0/imm32/false - 0f 84/jump-if-= $load-first-sector-from-primary-bus-secondary-drive:end/disp32 + 0f 84/jump-if-= $load-sector:end/disp32 # kick off read - (ata-drive-select 0xf0) # primary bus, secondary drive; 4 LSBs contain 4 upper bits of LBA (here 0) - (clear-ata-error) - (ata-sector-count 1) - (ata-lba 0 0 0) # lower 24 bits of LBA, all 0 - (ata-command 0x20) # read sectors with retries + (ata-drive-select *(ebp+8) *(ebp+0xc)) + (clear-ata-error *(ebp+8)) + (ata-sector-count *(ebp+8) 1) + (ata-lba *(ebp+8) *(ebp+0xc)) + (ata-command *(ebp+8) 0x20) # read sectors with retries # poll for results - (while-ata-busy) - (until-ata-data-available) + (while-ata-busy *(ebp+8)) + (until-ata-data-available *(ebp+8)) + # var data-port/edx = disk->data-port + 8b/-> *(ebp+8) 0/r32/eax + 8b/-> *(eax+0x24) 2/r32/edx + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "A: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } # emit results 31/xor %eax 0/r32/eax - ba/copy-to-edx 0x1f0/imm32 b9/copy-to-ecx 0x200/imm32 # 512 bytes per sector { 81 7/subop/compare %ecx 0/imm32 74/jump-if-= break/disp8 66 ed/read-port-dx-into-ax # write 2 bytes to stream one at a time - (append-byte *(ebp+8) %eax) + (append-byte *(ebp+0x10) %eax) 49/decrement-ecx c1/shift 5/subop/right-padding-zeroes %eax 8/imm8 - (append-byte *(ebp+8) %eax) + (append-byte *(ebp+0x10) %eax) 49/decrement-ecx eb/jump loop/disp8 } -$load-first-sector-from-primary-bus-secondary-drive:end: +$load-sector:end: # . restore registers 5a/pop-to-edx 59/pop-to-ecx @@ -861,7 +907,7 @@ $load-first-sector-from-primary-bus-secondary-drive:end: 5d/pop-to-ebp c3/return -store-first-sector-to-primary-bus-secondary-drive: # in: (addr stream byte) +store-sector: # disk: (addr disk), lba: int, in: (addr stream byte) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -871,40 +917,42 @@ store-first-sector-to-primary-bus-secondary-drive: # in: (addr stream byte) 52/push-edx 53/push-ebx # check for drive - (secondary-drive-exists?) # => eax + (drive-exists? *(ebp+8)) # => eax 3d/compare-eax-and 0/imm32/false - 0f 84/jump-if-= $store-first-sector-to-primary-bus-secondary-drive:end/disp32 + 0f 84/jump-if-= $store-sector:end/disp32 # kick off write - (ata-drive-select 0xf0) # primary bus, secondary drive; 4 LSBs contain 4 upper bits of LBA (here 0) - (clear-ata-error) - (ata-sector-count 1) - (ata-lba 0 0 0) # lower 24 bits of LBA, all 0 - (ata-command 0x30) # write sectors with retries + (ata-drive-select *(ebp+8) *(ebp+0xc)) + (clear-ata-error *(ebp+8)) + (ata-sector-count *(ebp+8) 1) + (ata-lba *(ebp+8) *(ebp+0xc)) + (ata-command *(ebp+8) 0x30) # write sectors with retries # wait - (while-ata-busy) - (until-ata-ready-for-data) + (while-ata-busy *(ebp+8)) + (until-ata-ready-for-data *(ebp+8)) + # var data-port/edx = disk->data-port + 8b/-> *(ebp+8) 0/r32/eax + 8b/-> *(eax+0x24) 2/r32/edx # send data - ba/copy-to-edx 0x1f0/imm32 b9/copy-to-ecx 0x200/imm32 # 512 bytes per sector - # var first-byte/ebx: byte - # when it's more than 0xff, we're at an even-numbered byte + # . var first-byte/ebx: byte + # . when it's more than 0xff, we're at an even-numbered byte bb/copy-to-ebx 0xffff/imm32 -$store-first-sector-to-primary-bus-secondary-drive:loop: +$store-sector:loop: { 81 7/subop/compare %ecx 0/imm32 74/jump-if-= break/disp8 # this loop is slow, but the ATA spec also requires a small delay - (stream-empty? *(ebp+8)) # => eax + (stream-empty? *(ebp+0x10)) # => eax 3d/compare-eax-and 0/imm32/false 75/jump-if-!= break/disp8 # read byte from stream - (read-byte *(ebp+8)) # => eax + (read-byte *(ebp+0x10)) # => eax # if we're at an odd-numbered byte, save it to first-byte 81 7/subop/compare %ebx 0xff/imm32 { 7e/jump-if-<= break/disp8 89/<- %ebx 0/r32/eax - eb/jump $store-first-sector-to-primary-bus-secondary-drive:loop/disp8 + eb/jump $store-sector:loop/disp8 } # otherwise OR it with first-byte and write it out c1/shift 4/subop/left %eax 8/imm8 @@ -935,7 +983,7 @@ $store-first-sector-to-primary-bus-secondary-drive:loop: 49/decrement-ecx eb/jump loop/disp8 } -$store-first-sector-to-primary-bus-secondary-drive:end: +$store-sector:end: # . restore registers 5b/pop-to-ebx 5a/pop-to-edx @@ -948,7 +996,7 @@ $store-first-sector-to-primary-bus-secondary-drive:end: # disk helpers {{{ -secondary-drive-exists?: # -> _/eax: boolean +drive-exists?: # disk: (addr disk) -> _/eax: boolean # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -958,37 +1006,69 @@ secondary-drive-exists?: # -> _/eax: boolean { 31/xor %eax 0/r32/eax ba/copy-to-edx 0x1f7/imm32 + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "B: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ec/read-port-dx-into-al 3d/compare-eax-and 0xff/imm32 # if eax is 0xff, primary bus has no drives b8/copy-to-eax 0/imm32/false - 74/jump-if-= $secondary-drive-exists?:end/disp8 + 74/jump-if-= $drive-exists?:end/disp8 } # identify - (ata-drive-select 0xf0) # primary bus, secondary drive - (ata-sector-count 0) - (ata-lba 0 0 0) - (ata-command 0xec) # identify - # read status register + (ata-drive-select *(ebp+8) 0) + (ata-sector-count *(ebp+8) 0) + (ata-lba *(ebp+8) 0) + (ata-command *(ebp+8) 0xec) # identify + # var status-port/edx = disk->status-port + 8b/-> *(ebp+8) 0/r32/eax + 8b/-> *(eax+4) 2/r32/edx # 4 = status-port offset + # read status port # TODO: might need to spin here for 400ns: https://wiki.osdev.org/index.php?title=ATA_PIO_Mode&oldid=25664#400ns_delays 31/xor %eax 0/r32/eax - ba/copy-to-edx 0x1f7/imm32 + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "C: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ec/read-port-dx-into-al - # if eax is 0, secondary drive does not exist + # if eax is 0, drive does not exist 3d/compare-eax-and 0/imm32 { 74/jump-if-= break/disp8 b8/copy-to-eax 1/imm32/true - eb/jump $secondary-drive-exists?:complete-identify/disp8 + eb/jump $drive-exists?:complete-identify/disp8 } # TODO: might need to perform remaining steps at https://wiki.osdev.org/index.php?title=ATA_PIO_Mode&oldid=25664#IDENTIFY_command b8/copy-to-eax 0/imm32/false -$secondary-drive-exists?:complete-identify: +$drive-exists?:complete-identify: 50/push-eax + # var data-port/edx = disk->data-port + 8b/-> *(ebp+8) 0/r32/eax + 8b/-> *(eax+0x24) 2/r32/edx # 0x24 = data-port offset # clear FIFO from the drive - ba/copy-to-edx 0x1f0/imm32 b9/copy-to-ecx 0x200/imm32 { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "D: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } + { 81 7/subop/compare %ecx 0/imm32 74/jump-if-= break/disp8 # read 4 bytes @@ -1000,7 +1080,7 @@ $secondary-drive-exists?:complete-identify: eb/jump loop/disp8 } 58/pop-to-eax -$secondary-drive-exists?:end: +$drive-exists?:end: # . restore registers 5a/pop-to-edx # . epilogue @@ -1008,19 +1088,45 @@ $secondary-drive-exists?:end: 5d/pop-to-ebp c3/return -ata-drive-select: # n: byte +ata-drive-select: # disk: (addr disk), lba: int # . 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 + 56/push-esi + # esi = disk + 8b/-> *(ebp+8) 6/r32/esi + # var drive-head/edx: byte = lba >> 24 + 8b/-> *(ebp+0xc) 2/r32/edx + c1/shift 5/subop/right-padding-zeroes %edx 0x18/imm8 + # var drive-code/eax: byte = disk->drive-code | drive-head + 8b/-> *(esi+0x28) 0/r32/eax # 0x28 = drive-code offset + 09/or= %eax 2/r32/edx + # var drive-and-head-port/edx: int + 8b/-> *(esi+0x10) 2/r32/edx # 0x10 = drive-and-head-port offset + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "E: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + 59/pop-to-ecx + 58/pop-to-eax + } + { + 50/push-eax + 51/push-ecx + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ee/write-al-into-port-dx $ata-drive-select:end: # . restore registers + 5e/pop-to-esi 5a/pop-to-edx 58/pop-to-eax # . epilogue @@ -1028,16 +1134,35 @@ $ata-drive-select:end: 5d/pop-to-ebp c3/return -clear-ata-error: +clear-ata-error: # disk: (addr disk) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 50/push-eax 52/push-edx + # var error-port/edx = disk->error-port + 8b/-> *(ebp+8) 0/r32/eax + 8b/-> *(eax+0xc) 2/r32/edx # 0xc = error-port offset # b8/copy-to-eax 0/imm32 - ba/copy-to-edx 0x1f1/imm32 + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "F: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + 59/pop-to-ecx + 58/pop-to-eax + } + { + 50/push-eax + 51/push-ecx + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ee/write-al-into-port-dx $ata-error:end: # . restore registers @@ -1048,16 +1173,35 @@ $ata-error:end: 5d/pop-to-ebp c3/return -ata-sector-count: # n: byte +ata-sector-count: # disk: (addr disk), n: byte # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 50/push-eax 52/push-edx - # + # var sector-count-port/edx = disk->sector-count-port 8b/-> *(ebp+8) 0/r32/eax - ba/copy-to-edx 0x1f2/imm32 + 8b/-> *(eax+0x14) 2/r32/edx # 0x14 = sector-count-port offset + # + 8b/-> *(ebp+0xc) 0/r32/eax + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "G: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + 59/pop-to-ecx + 58/pop-to-eax + } + { + 50/push-eax + 51/push-ecx + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ee/write-al-into-port-dx $ata-sector-count:end: # . restore registers @@ -1068,24 +1212,68 @@ $ata-sector-count:end: 5d/pop-to-ebp c3/return -ata-lba: # lo: byte, mid: byte, hi: byte +ata-lba: # disk: (addr disk), lba: int # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 50/push-eax 52/push-edx - # lo + # var port/edx = disk->port 8b/-> *(ebp+8) 0/r32/eax - ba/copy-to-edx 0x1f3/imm32 + 8b/-> *(eax+0x18) 2/r32/edx # 0x18 = lba-low-port offset + # eax = lba + 8b/-> *(ebp+0xc) 0/r32/eax + # lo + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "H: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + 59/pop-to-ecx + 58/pop-to-eax + } + { + 50/push-eax + 51/push-ecx + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ee/write-al-into-port-dx # mid - 8b/-> *(ebp+0xc) 0/r32/eax - ba/copy-to-edx 0x1f4/imm32 + 42/increment-dx # lba-mid-port + c1/shift 5/subop/right-padding-zeroes %eax 8/imm8 + { + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "I: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 7 0) + (move-cursor-to-left-margin-of-next-line 0) + } ee/write-al-into-port-dx # hi - 8b/-> *(ebp+0x10) 0/r32/eax - ba/copy-to-edx 0x1f5/imm32 + 42/increment-dx # lba-high-port + c1/shift 5/subop/right-padding-zeroes %eax 8/imm8 + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "J: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + 59/pop-to-ecx + 58/pop-to-eax + } + { + 50/push-eax + 51/push-ecx + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ee/write-al-into-port-dx $ata-lba:end: # . restore registers @@ -1096,46 +1284,35 @@ $ata-lba:end: 5d/pop-to-ebp c3/return -# sector: [1, 63] -# cylinder: [0, 1023] -ata-cyl-sector: # sector: byte, cyl-lo: byte, cyl-hi: byte +ata-command: # disk: (addr disk), cmd: byte # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 50/push-eax 52/push-edx - # sector + # var command-port/edx = disk->command-port 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/-> *(eax+0) 2/r32/edx # 0 = command-port offset # - 8b/-> *(ebp+8) 0/r32/eax - ba/copy-to-edx 0x1f7/imm32 + 8b/-> *(ebp+0xc) 0/r32/eax + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "K: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 7 0) + 59/pop-to-ecx + 58/pop-to-eax + } + { + 50/push-eax + 51/push-ecx + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } ee/write-al-into-port-dx $ata-command:end: # . restore registers @@ -1146,12 +1323,22 @@ $ata-command:end: 5d/pop-to-ebp c3/return -while-ata-busy: +while-ata-busy: # disk: (addr disk) # . save registers 50/push-eax 52/push-edx - # - ba/copy-to-edx 0x1f7/imm32 + # var status-port/edx = disk->status-port + 8b/-> *(ebp+8) 0/r32/eax + 8b/-> *(eax+4) 2/r32/edx # 4 = status-port offset + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "L: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } { ec/read-port-dx-into-al a8/test-bits-in-al 0x80/imm8/bsy # set zf if bit 7 (most significant) is not set @@ -1164,12 +1351,22 @@ $while-ata-busy:end: # . epilogue c3/return -until-ata-data-available: +until-ata-data-available: # disk: (addr disk) # . save registers 50/push-eax 52/push-edx - # - ba/copy-to-edx 0x1f7/imm32 + # var status-port/edx = disk->status-port + 8b/-> *(ebp+8) 0/r32/eax + 8b/-> *(eax+4) 2/r32/edx # 4 = status-port offset + { + 50/push-eax + 51/push-ecx + (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "M: " 7 0) + (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 7 0) + (move-cursor-to-left-margin-of-next-line 0) + 59/pop-to-ecx + 58/pop-to-eax + } { ec/read-port-dx-into-al a8/test-bits-in-al 8/imm8/drq # set zf if bit 3 is not set |