Author: wmb Date: 2008-01-28 05:19:49 +0100 (Mon, 28 Jan 2008) New Revision: 794
Modified: cpu/x86/pc/biosload/callbios.fth cpu/x86/pc/biosload/fw.bth cpu/x86/pc/biosload/rmenter.fth Log: BIOSload version - checkpoint of BIOS gateway code.
Modified: cpu/x86/pc/biosload/callbios.fth =================================================================== --- cpu/x86/pc/biosload/callbios.fth 2008-01-28 04:18:50 UTC (rev 793) +++ cpu/x86/pc/biosload/callbios.fth 2008-01-28 04:19:49 UTC (rev 794) @@ -9,42 +9,41 @@
\ We assume that we can use memory from h# 200 to h# 3ff
-\ Bounce buffer at h# 90000 - h# 8 constant rm-code-desc h# 18 constant rm-data-desc h# 20 constant pm-code-desc h# 28 constant pm-data-desc
-h# 002 constant rm-flagval \ Flags for IRET +h# 002 constant bios-flagval \ Flags for IRET
\ Low-memory addresses -h# 200 constant rm-go \ Real mode enter code -h# 280 constant rm-return \ Real mode return code -h# 300 constant rm-idt \ For loading RM IDT with LIDT -h# 308 constant rm-sp \ For loading RM SP with LSS +h# 200 constant 'bios-call \ Real mode enter code +h# 280 constant 'bios-ret \ Real mode return code +h# 300 constant 'bios-idt \ For loading RM IDT with LIDT +h# 308 constant 'bios-sp \ For loading RM SP with LSS h# 30c constant pm-sp-save \ Save/restore area for PM SP h# 310 constant pm-gdt-save \ For loading PM GDT with LGDT h# 318 constant pm-idt-save \ For loading PM IDT with LIDT -h# 3c0 constant rm-regs \ Real-mode register buffer (in/out) -rm-regs constant rm-gs -rm-gs wa1+ constant rm-fs -rm-fs wa1+ constant rm-es -rm-es wa1+ constant rm-ds -rm-ds wa1+ constant rm-di -rm-di la1+ constant rm-si -rm-si la1+ constant rm-bp -rm-bp la1+ constant rm-xx \ Would be stack pointer -rm-xx la1+ constant rm-bx -rm-bx la1+ constant rm-dx -rm-dx la1+ constant rm-cx -rm-cx la1+ constant rm-ax -rm-ax la1+ constant rm-flags -rm-flags la1+ constant rm-target \ Full pointer for RM call target address -rm-target la1+ constant rm-retloc \ Full pointer to rm-return -rm-retloc la1+ constant rm-rflags \ Flags in case of return via IRET
-label rmint-enter +h# 3c0 constant bios-regs \ Real-mode register buffer (in/out) +bios-regs constant bios-gs +bios-gs wa1+ constant bios-fs +bios-fs wa1+ constant bios-es +bios-es wa1+ constant bios-ds +bios-ds wa1+ constant bios-di \ offset decimal 8 +bios-di la1+ constant bios-si +bios-si la1+ constant bios-bp +bios-bp la1+ constant bios-xx \ Would be stack pointer +bios-xx la1+ constant bios-bx +bios-bx la1+ constant bios-dx +bios-dx la1+ constant bios-cx +bios-cx la1+ constant bios-ax +bios-ax la1+ constant bios-flags \ offset decimal 40 +bios-flags la1+ constant bios-target \ Full pointer for RM call target address +bios-target la1+ constant bios-retloc \ Full pointer to 'bios-ret +bios-retloc la1+ constant bios-rflags \ Flags in case of return via IRET + +label bios-call real-mode \ This must be copied to low memory
@@ -54,25 +53,25 @@ pm-gdt-save #) sgdt \ So we can get back pm-idt-save #) sidt \ So we can get back
- rm-idt #) lidt + 'bios-idt #) lidt cr0 ax mov h# fe # al and ax cr0 mov \ Enter real mode
- here 5 + rmint-enter - rm-go + 0 #) far jmp \ Jump to set cs + here 5 + bios-call - 'bios-call + 0 #) far jmp \ Jump to set cs
\ Now we are running in real mode; fix segments again cs ax mov ax ds mov ax es mov ax fs mov ax gs mov
- rm-sp #) sp lss + 'bios-sp #) sp lss
- \ Load the 16-bit registers from the rm-regs area + \ Load the 16-bit registers from the bios-regs area gs pop fs pop es pop ds pop op: popa op: popf
far ret \ Now we are running the real-mode target code end-code -here rmint-enter - constant /rmint-enter +here bios-call - constant /bios-call
-label rmint-exit - rm-target # sp mov \ Set the stack pointer to the top of the rm reg area +label bios-ret + bios-target # sp mov \ Set the stack pointer to the top of the rm reg area
\ Copy the real-mode registers to the buffer op: pushf op: pusha ds push es push fs push gs push @@ -83,7 +82,7 @@ op: pm-gdt-save #) lgdt cr0 ax mov 1 # al or ax cr0 mov
- here 5 + rmint-exit - rm-return + pm-code-desc #) far jmp + here 5 + bios-ret - 'bios-ret + pm-code-desc #) far jmp
protected-mode
@@ -94,10 +93,10 @@ popf popa c; -here rmint-exit - constant /rmint-exit +here bios-ret - constant /bios-ret
\ Must set up the registers area with register values and the target address -code rm-call ( -- ) +code }bios ( -- ) pusha pushf
@@ -105,108 +104,130 @@ cld cli sp sp xor - rm-go rm-code-desc #) far jmp + 'bios-call rm-code-desc #) far jmp c;
: >seg:off ( linear -- offset segment ) lwsplit d# 12 lshift ; : seg:off! ( linear adr -- ) >r >seg:off r@ 2+ w! r> w! ; +: seg:off> ( offset segment -- linear ) 4 lshift + ; +: seg:off@ ( adr -- linear ) dup w@ swap wa1+ w@ seg:off> ;
0 value bios-prepped? : ?prep-bios-call ( -- ) bios-prepped? if exit then true to bios-prepped? - rmint-enter rm-go /rmint-enter move - rmint-exit rm-return /rmint-exit move - h# ffff rm-idt w! - 0 rm-idt 2+ l! - rm-regs rm-sp seg:off! \ Setup real-mode full pointer for lss - rm-return rm-retloc seg:off! \ Setup return address full pointer - rm-flagval rm-retloc 4 + w! \ Flags for return + bios-call 'bios-call /bios-call move + bios-ret 'bios-ret /bios-ret move + h# ffff 'bios-idt w! + 0 'bios-idt 2+ l! + bios-regs 'bios-sp seg:off! \ Setup real-mode full pointer for lss + 'bios-ret bios-retloc seg:off! \ Setup return address full pointer + bios-flagval bios-retloc 4 + w! \ Flags for return ;
-: dr - ." ax: " rm-ax ? 2 spaces - ." bx: " rm-bx ? 2 spaces - ." cx: " rm-cx ? 2 spaces - ." dx: " rm-dx ? 2 spaces - ." bp: " rm-bp ? 2 spaces - ." si: " rm-si ? 2 spaces - ." di: " rm-di ? 2 spaces +: .bios-regs + ." ax: " bios-ax ? 2 spaces + ." bx: " bios-bx ? 2 spaces + ." cx: " bios-cx ? 2 spaces + ." dx: " bios-dx ? 2 spaces + ." bp: " bios-bp ? 2 spaces + ." si: " bios-si ? 2 spaces + ." di: " bios-di ? 2 spaces + cr + ." ds: " bios-ds w@ . 2 spaces + ." es: " bios-es w@ . 2 spaces + ." fs: " bios-fs w@ . 2 spaces + ." gs: " bios-gs w@ . 2 spaces + ." flags: " bios-flags ? + cr ;
-: { ( int# -- ) ?prep-bios-call rm-regs d# 44 erase 4 * @ rm-target ! ; -: } rm-call ; +: bios{ ( int# -- ) ?prep-bios-call bios-regs d# 44 erase 4 * @ bios-target ! ;
-: ax rm-ax ! ; -: ah rm-ax 1+ c! ; -: al rm-ax c! ; -: bx rm-bx l! ; -: cx rm-cx l! ; -: dx rm-dx l! ; -: cf@ rm-flags @ 1 and ; -: es:di >seg:off rm-es w! rm-di l! ; +: ax bios-ax ! ; +: ah bios-ax 1+ c! ; +: al bios-ax c! ; +: bx bios-bx l! ; +: cx bios-cx l! ; +: dx bios-dx l! ; +: cf@ bios-flags @ 1 and ; +: es:di >seg:off bios-es w! bios-di l! ; + +\ Video - INT 10 : video-mode ( mode# -- ) - d# 55 set-tick-limit h# 10 { 3 al bx } d# 10 set-tick-limit + d# 55 set-tick-limit h# 10 bios{ 3 al bx }bios d# 10 set-tick-limit ; : text-mode 3 video-mode ; : 1024x768x8 h# 105 video-mode ; : 1024x768x16 h# 116 video-mode ; -: apm-connect16 h# 15 { h# 5302 ax 0 bx } ; -: apm-power-off apm-connect16 h# 15 { h# 5307 ax 1 bx 3 cx } ; +: apm-connect16 h# 15 bios{ h# 5302 ax 0 bx }bios ; +: apm-power-off apm-connect16 h# 15 bios{ h# 5307 ax 1 bx 3 cx }bios ; + +\ Memory map - INT 15 : bios-memsize ( -- n ) - h# 15 { h# e801 ax } - rm-ax @ h# 400 * rm-bx @ h# 10000 * + h# 100000 + + h# 15 bios{ h# e801 ax }bios + bios-ax @ h# 400 * bios-bx @ h# 10000 * + h# 100000 + ; : .bios-memory-map ( -- ) 0 begin ( continuation ) - h# 15 { bx h# e820 ax h# 10000 es:di d# 20 cx " PAMS" drop @ dx } - rm-flags @ 1 and abort" Not supported" - rm-cx @ - h# 10000 rm-cx @ bounds ?do i @ 9 u.r 4 +loop cr - rm-bx @ ( continuation' ) + h# 15 bios{ bx h# e820 ax h# 10000 es:di d# 20 cx " PAMS" drop @ dx }bios + bios-flags @ 1 and abort" Not supported" + h# 10000 bios-cx @ bounds ?do i @ 9 u.r 4 +loop cr + bios-bx @ ( continuation' ) ?dup 0= until ; -: bios-config-b@ ( adr -- b ) lwsplit h# 1a { h# b108 ax bx rm-di ! } rm-cx @ ; -: bios-config-w@ ( adr -- w ) lwsplit h# 1a { h# b109 ax bx rm-di ! } rm-cx @ ; -: bios-config-l@ ( adr -- l ) lwsplit h# 1a { h# b10a ax bx rm-di ! } rm-cx @ ; -: bios-config-b! ( b adr -- ) lwsplit h# 1a { h# b10b ax bx rm-di ! rm-cx ! } ; -: bios-config-w! ( w adr -- ) lwsplit h# 1a { h# b10c ax bx rm-di ! rm-cx ! } ; -: bios-config-l! ( l adr -- ) lwsplit h# 1a { h# b10d ax bx rm-di ! rm-cx ! } ; -: disk-status ( -- stat ) h# 13 { h# 0100 ax } rm-ax @ ; + +\ PCI BIOS - INT 1A +: (bios-config@) ( adr axval -- n ) + h# 1a bios{ ax lwsplit bx bios-di ! }bios bios-cx @ +; +: (bios-config!) ( n adr axval -- ) + h# 1a bios{ ax lwsplit bx bios-di ! bios-cx ! }bios +; + +: bios-config-b@ ( adr -- b ) h# b108 (bios-config@) ; +: bios-config-w@ ( adr -- w ) h# b109 (bios-config@) ; +: bios-config-l@ ( adr -- l ) h# b10a (bios-config@) ; +: bios-config-b! ( b adr -- ) h# b10b (bios-config!) ; +: bios-config-w! ( w adr -- ) h# b10c (bios-config!) ; +: bios-config-l! ( l adr -- ) h# b10d (bios-config!) ; + +\ Disk access - INT 13 +: disk-status ( -- stat ) h# 13 bios{ h# 0100 ax }bios bios-ax @ ; + 0 value #sects 0 value #cyls 0 value #heads : get-drive-params ( -- ) - h# 13 { 8 ah h# 80 dx } - rm-flags @ 1 and if true exit then - rm-cx @ wbsplit ( cl ch ) - over h# 3f and to #sects ( cl ch ) - swap 6 rshift bwjoin 1+ to #cyls ( ) - rm-dx @ 8 rshift 1+ to #heads ( ) + h# 13 bios{ 8 ah h# 80 dx }bios + bios-flags @ 1 and if true exit then + bios-cx @ wbsplit ( cl ch ) + over h# 3f and to #sects ( cl ch ) + swap 6 rshift bwjoin 1+ to #cyls ( ) + bios-dx @ 8 rshift 1+ to #heads ( ) ; : #drive-sectors ( -- n ) - h# 13 { h# 15 ah h# 80 dx } - rm-dx @ rm-cx @ wljoin + h# 13 bios{ h# 15 ah h# 80 dx }bios + bios-dx @ bios-cx @ wljoin ; -: reset-disks ( -- ) h# 13 { 0 ah h# 80 dx } ; -: reset-hard-disks ( -- ) h# 13 { h# 0d ah h# 80 dx } ; -: do-rw ( sector1 cyl0 head0 drive0 #sectors ah-val -- ) - h# 13 { ah al ( sector1 cyl0 head0 drive0 ) - swap bwjoin dx ( sector1 cyl0 ) - wbsplit ( sector1 cyl.lo cyl.hi ) - 6 lshift rot or ( cyl.lo cyl.hi|sector ) +: reset-disks ( -- ) h# 13 bios{ 0 ah h# 80 dx }bios ; +: reset-hard-disks ( -- ) h# 13 bios{ h# 0d ah h# 80 dx }bios ; +: bios-rw ( sector1 head0 cyl0 drive0 #sectors ah-val -- ) + h# 13 bios{ ah al ( sector1 head0 cyl0 drive0 ) + rot bwjoin dx ( sector1 cyl0 ) + wbsplit ( sector1 cyl.lo cyl.hi ) + 6 lshift rot or ( cyl.lo cyl.hi|sector ) swap bwjoin cx - h# 10000 >seg:off rm-es w! bx - } + h# 10000 >seg:off bios-es w! bx + }bios ; -: read-sectors ( sector1 cyl0 head0 drive0 #sectors -- ) 2 do-rw ; -: write-sectors ( sector1 cyl0 head0 drive0 #sectors -- ) 3 do-rw ; +: bios-read-sectors ( sector1 head0 cyl0 drive0 #sectors -- ) 2 bios-rw ; +: bios-write-sectors ( sector1 head0 cyl0 drive0 #sectors -- ) 3 bios-rw ;
-: lbn>sch ( lbn -- sector cyl head ) - #sects /mod swap 1+ swap ( sector rem ) - #heads /mod ( sector head cyl ) - dup #cyls > abort" LBN out of range" - swap ( sector cyl head ) +: lbn>shc ( lbn -- sector head cyl ) + #sects /mod swap 1+ swap ( sector rem ) + #heads /mod ( sector head cyl ) + dup #cyls > abort" LBN out of range" ( sector head cyl ) ; -: lbn-read-sectors ( lbn drive #sectors -- ) 2>r lbn>sch 2r> read-sectors ; -: lbn-write-sectors ( lbn drive #sectors -- ) 2>r lbn>sch 2r> write-sectors ; +: lbn-read-sectors ( lbn drive #sectors -- ) 2>r lbn>shc 2r> bios-read-sectors ; +: lbn-write-sectors ( lbn drive #sectors -- ) 2>r lbn>shc 2r> bios-write-sectors ;
Modified: cpu/x86/pc/biosload/fw.bth =================================================================== --- cpu/x86/pc/biosload/fw.bth 2008-01-28 04:18:50 UTC (rev 793) +++ cpu/x86/pc/biosload/fw.bth 2008-01-28 04:19:49 UTC (rev 794) @@ -206,7 +206,7 @@ ;
fload ${BP}/cpu/x86/pc/biosload/usb.fth -\ fload ${BP}/cpu/x86/pc/biosload/callbios.fth +fload ${BP}/cpu/x86/pc/biosload/callbios.fth fload ${BP}/cpu/x86/pc/biosload/rmenter.fth
\ false to stand-init-debug? @@ -275,7 +275,7 @@ warning on only forth also definitions
- install-alarm +\ install-alarm
#line off
@@ -323,6 +323,7 @@
.( Saving fw.img ...) " fw.img" RAMbase save-abs-rom cr + \ LICENSE_BEGIN \ Copyright (c) 2006 FirmWorks \
Modified: cpu/x86/pc/biosload/rmenter.fth =================================================================== --- cpu/x86/pc/biosload/rmenter.fth 2008-01-28 04:18:50 UTC (rev 793) +++ cpu/x86/pc/biosload/rmenter.fth 2008-01-28 04:19:49 UTC (rev 794) @@ -1,3 +1,4 @@ +[ifndef] >seg:off : >seg:off ( linear -- offset segment ) lwsplit d# 12 lshift ; : seg:off! ( linear adr -- ) >r >seg:off r@ wa1+ w! r> w! ; : seg:off> ( offset segment -- linear ) 4 lshift + ; @@ -2,2 +3,3 @@ : seg:off@ ( adr -- linear ) dup w@ swap wa1+ w@ seg:off> ; +[then]
@@ -27,8 +29,11 @@ h# 0.0000 constant rm-base : +rm ( offset -- adr ) rm-base + ;
+\ The real-mode stack pointer will start here +h# f00 +rm constant 'rm-stack +\ h# ef0 +rm constant 'rm-dispatch + \ Place for the initial registers upon entry to real mode. -\ The real-mode stack pointer will start here h# f00 +rm constant 'rm-regs \ (00) 4 * 2: GS,FS,ES,DS \ (08) 8 * 4: EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX @@ -97,8 +102,25 @@ : rm-flags! caller-regs >rm-flags w! ;
: rm-set-cf rm-flags@ 1 or rm-flags! ; -: rm-clr-cf rm-flags@ 1 or rm-flags! ; +: rm-clr-cf rm-flags@ 1 invert and rm-flags! ;
+true value show-rm-int? +: noshow false to show-rm-int? ; +variable save-eax +: snap-int + true to show-rm-int? caller-regs >rm-eax @ save-eax ! +; +: showint + ." INT " 'rm-int w@ . save-eax @ wbsplit ." AH " . ." AL " . cr +; +: ?showint show-rm-int? if showint then ; + +h# 80 constant /vectors + +/vectors buffer: saved-rm-vectors +/vectors buffer: saved-ofw-vectors + + \ 80ff0 is the target address of the interrupt vector \ We use different segment:offset representations of that address in \ the vector table, so the handler code can determine the vector @@ -108,13 +130,29 @@ \ ... \ ff: 80ff:0000
+: grab-rm-vector ( vector# -- ) + >r + h# ff0 r@ 4 lshift - r@ /l* w! \ Set offset + rm-base 4 rshift r@ + r> /l* wa1+ w! \ Set segment +; +: ungrab-rm-vector ( vector# -- ) + saved-rm-vectors over la+ l@ ( vector# value ) + swap /l* l! +; : make-vector-table ( -- ) - h# 100 0 do - h# ff0 i 4 lshift - i /l* w! \ Set offset - rm-base 4 rshift i + i /l* wa1+ w! \ Set segment - loop + h# 100 0 do i grab-rm-vector loop ;
+label timer-off + real-mode + ax push + h# 21 # al in + 1 # al or + al h# 21 # out + ax pop + iret +end-code + label rm-to-pm real-mode
@@ -205,40 +243,123 @@ end-code here rm-enter - constant /rm-enter
-h# 400 buffer: saved-rm-vectors +: restore-vector ( int# -- ) + saved-rm-vectors over la+ l@ swap /l* l! +;
0 value rm-prepped? +: move-gdt ( -- ) + gdtr@ 1+ ( gdt-adr gdt-len ) + +\ dup h# 10 + alloc-mem h# f + h# f invert and ( gdt-adr gdt-len new-gdt ) + h# 900 + + swap 2dup 2>r move 2r> ( new-gdt gdt-len ) + 1- gdtr! +; +0 value kbd-ih + +: bios-vectors ( -- ) + 0 saved-ofw-vectors /vectors move + saved-rm-vectors 0 /vectors move +; +: ofw-vectors ( -- ) +\ 0 saved-ofw-vectors /vectors move + saved-ofw-vectors 0 /vectors move +; +: regs>bios ( -- ) + caller-regs bios-regs d# 40 move + rm-flags@ bios-flags l! + 'rm-int w@ /l* @ bios-target ! +; +: bios>regs ( -- ) + bios-regs caller-regs d# 40 move + bios-flags l@ rm-flags! +; +: use-bios ( -- ) + bios-vectors + ?prep-bios-call + regs>bios + }bios + bios>regs + ofw-vectors +; + : prep-rm ( -- ) rm-prepped? if exit then true to rm-prepped? fix-gdt - 0 saved-rm-vectors h# 400 move - make-vector-table
+ move-gdt + rm-enter 'rm-enter /rm-enter move rm-to-pm 'rm-to-pm /rm-to-pm move pm-to-rm 'pm-to-rm /pm-to-rm move
+ 0 saved-rm-vectors /vectors move + +[ifdef] syslinux-loaded + 7 h# 1.0004 config-w! + + h# 10 grab-rm-vector \ Video + h# 11 grab-rm-vector \ Sysinfo + h# 12 grab-rm-vector \ Low memory size + h# 13 grab-rm-vector \ Disk I/O +\ h# 15 grab-rm-vector \ Various system stuff + h# 16 grab-rm-vector \ Keyboard + h# 1a grab-rm-vector \ PCI BIOS +[else] + make-vector-table + + saved-rm-vectors 8 la+ l@ 0 8 la+ l! \ Use BIOS timer tick handler + saved-rm-vectors h# 1c la+ l@ 0 h# 1c la+ l! \ Timer handler chain +[then] + +\ \ Set up a rudimentary handler for the ISA timer +\ timer-off 'rm-timer-off /rm-timer-off move +\ 'rm-timer-off 0 8 la+ seg:off! + h# ffff 'rm-idt w! 0 'rm-idt wa1+ l! \ Limit and base + + " keyboard" open-dev to kbd-ih ;
: rm-init-program ( pc -- ) prep-rm 'rm-regs h# 2e erase ( pc ) 'rm-regs h# 28 + seg:off! ( ) - 'rm-regs 'rm-sp seg:off! \ Initial stack pointer below regs + 'rm-stack 'rm-sp seg:off! \ Initial stack pointer below regs ;
+: !font ( adr -- ) + >seg:off caller-regs >rm-es w! caller-regs >rm-ebp l! + h# 10 rm-cx! h# 18 rm-dx! +; : get-font ( -- ) rm-al@ h# 30 = if ." Int 10 get-font called - BH = " rm-bh@ . cr + rm-bh@ case +\ These numbers are cheats, pointing into the VIA BIOS + 2 of h# c69e0 !font endof + 3 of h# c6138 !font endof + 4 of h# c6538 !font endof + 5 of h# c69e0 !font endof + 6 of h# c77e0 !font endof + 7 of h# c77e0 !font +h# 10 ungrab-rm-vector +endof + ( default ) ." Unsupported get font - BH = " dup . cr rm-set-cf + endcase else ." Int 10 set-font called" cr then ;
-: video-int ( -- ) +: set-cursor ( -- ) rm-dh@ rm-dl@ ( row column ) 2drop ; + +: video-int ( -- ) \ INT 10 rm-ah@ case h# 0 of ( rm-al@ set-video-mode ) endof \ Set mode - Should blank the screen + h# 2 of set-cursor endof h# a of rm-al@ emit endof \ Write character h# e of rm-al@ emit endof \ Write character h# 11 of get-font endof \ get or set font @@ -248,13 +369,29 @@ ( default ) ." Unimplemented video int - AH = " dup . cr rm-set-cf endcase ; -: sysinfo-int ( -- ) h# 26 rm-ax! ; +: bios-video-int debug-me use-bios ;
+: sysinfo-int ( -- ) \ INT 11 + \ h# 4226 caller-regs >rm-eax ! \ to report 1 parallel and 1 serial port + h# 26 caller-regs >rm-eax ! \ 32 bits +; + 0 value disk-ih : disk-read-sectors ( adr sector# #sectors -- #read ) +noshow +\ ." Read " 2 pick . over . dup . ." -- " +\ over h# 8b74aaa = if debug-me then " read-blocks" disk-ih $call-method +\ dup . cr ;
+: disk-write-sectors ( adr sector# #sectors -- #read ) +\ ." Write " 2 pick . over . dup . ." -- " +\ over h# 8b74aaa = if debug-me then + " write-blocks" disk-ih $call-method +\ dup . cr +; + 0 [if] h# 200 constant /sector : disk-seek ( sector# -- error? ) @@ -274,8 +411,9 @@ rm-dl@ h# 80 <> if rm-set-cf 7 rm-ah! true exit then disk-ih if false exit then \ " disk:0" open-dev to disk-ih - " /ide@0" open-dev to disk-ih + " /pci/ide@0" open-dev to disk-ih disk-ih dup 0= if rm-set-cf h# aa rm-ah! then + false ; : read-sectors ( -- ) check-drive if exit then @@ -292,13 +430,15 @@ \ rm-bx@ caller-regs >rm-es w@ seg:off> rm-al@ ( adr #sectors ) \ disk-read rm-al! ; +: drive-sectors ( -- n ) " #blocks" disk-ih $call-method ; : drive-params ( -- ) check-drive if exit then \ " size" disk-ih $call-method ( d.#bytes ) \ /sector um/mod nip ( #sectors ) - " #blocks" disk-ih $call-method ( #sectors ) + drive-sectors ( #sectors ) h# 3f / ( #tracks ) h# ff / 1- ( maxcyl ) \ Max 255 heads is traditional +\ dup ." MAXCYL " . cr wbsplit ( maxcyl.lo maxcyl.hi ) 3 min 6 lshift h# 3f or rm-cl! ( maxcyl.lo ) \ High cyl, max sector rm-ch! ( ) \ Low byte of max cylinder @@ -307,16 +447,33 @@ rm-clr-cf ;
+: ds:si ( -- adr ) + caller-regs >rm-esi w@ caller-regs >rm-ds w@ seg:off> +; : lba-read ( -- ) check-drive if exit then - caller-regs >rm-esi w@ caller-regs >rm-ds w@ seg:off> ( packet-adr ) - >r r@ 4 + seg:off@ r@ 8 + l@ r@ 2+ w@ disk-read-sectors r> 2+ w! + ds:si ( packet-adr ) + >r r@ 4 + seg:off@ r@ 8 + l@ r@ 2+ w@ ( adr sector# #sectors ) +\ ." LBA " + disk-read-sectors r> 2+ w! \ dup 8 + l@ ( packet-adr sector# ) \ disk-seek if drop exit then ( packet-adr ) \ dup 4 + seg:off@ over 2+ w@ ( packet-adr adr #sectors ) \ disk-read \ swap 2+ w! ; +: lba-write ( -- ) + check-drive if exit then + ds:si ( packet-adr ) + >r r@ 4 + seg:off@ r@ 8 + l@ r@ 2+ w@ ( adr sector# #sectors ) +\ ." LBA " + disk-write-sectors r> 2+ w! +\ dup 8 + l@ ( packet-adr sector# ) +\ disk-seek if drop exit then ( packet-adr ) +\ dup 4 + seg:off@ over 2+ w@ ( packet-adr adr #sectors ) +\ disk-read +\ swap 2+ w! +;
: check-disk-extensions ( -- ) check-drive if 0 rm-bx! exit then @@ -324,13 +481,42 @@ h# aa55 rm-bx! h# 20 rm-ah! 1 rm-cx! ; +: ext-get-drive-params ( -- ) + check-drive if exit then + 0 rm-ah! + ds:si >r ( adr ) + r@ 2 + h# 0e erase \ CHS info not valid + drive-sectors r@ h# 10 + l! 0 r@ h# 14 + l! \ Total #sectors + h# 200 r@ h# 18 + w! \ Sector len + h# 1a ( written-length ) + r@ w@ h# 1e >= if + -1 r@ h# 1a + l! \ No EDD + 4 + ( written-length' ) + then ( written-length ) + r@ w@ h# 20 >= if ( written-length ) + 0 r@ h# 1e + w! \ Ensure that device path info not interpreted + \ Don't claim these bytes + then ( written-length ) + r> w! \ Number of bytes written + rm-clr-cf +;
+: get-disk-type ( -- ) + check-drive if exit then + 3 rm-ah! + drive-sectors lwsplit rm-cx! rm-dx! + rm-clr-cf +; + : disk-int ( -- ) \ INT 13 handler rm-ah@ case - h# 02 of read-sectors endof - h# 08 of drive-params endof + h# 02 of noshow read-sectors endof + h# 08 of drive-params endof + h# 15 of get-disk-type endof h# 41 of check-disk-extensions endof - h# 42 of lba-read endof + h# 42 of lba-read endof + h# 43 of lba-write endof + h# 48 of ext-get-drive-params endof ( default ) ." Unsupported disk INT 13 - AH = " dup . cr endcase ; @@ -354,11 +540,74 @@ dup h# 100.0000 min h# 10.0000 - 0 max /1k dup rm-ax! rm-cx! h# 100.0000 - 0 max d# 16 rshift dup rm-bx! rm-dx! ; +: allmem ( -- n ) + " /memory" find-package 0= abort" No /memory node" ( phandle ) + " reg" rot get-package-property abort" No available property" ( $ ) + decode-int drop get-encoded-int h# 10.0000 round-up +; + +0 [if] +Entry: + EBX Continuation value + ES:DI Address of Address Range Descriptor + ECX Length of Address Range Descriptor (=> 20 bytes) + EDX "SMAP" signature +Exit: + Carry 0 = E820 Supported + EAX "SMAP" signature + ES:DI Same value as entry + ECX Length of actual reported information in bytes + EBX Continuation value + Structure of Address Range Descriptor: + Bytes 0-3 Low 32 bits of Base Address + Bytes 4-7 High 32 bits of Base Address + Bytes 8-11 Low 32 bits of Length in bytes + Bytes 12-15 High 32 bits of Length in bytes + Bytes 16-20 Type of Address Range: + 1 = AddressRangeMemory, available to OS + 2 = AddressRangeReserved, not available + 3 = AddressRangeACPI, available to OS + 4 = AddressRangeNVS, not available to OS + Other = Not defined, not available + +d.base d.len l.type +[then] + +create memdescs + h# 0. d, h# a0000. d, 1 l, \ 0 +\ h# a0000. d, h# 60000. d, 2 l, \ 14 + h# f0000. d, h# 10000. d, 2 l, \ 14 + h# 100000. d, 0. d, 1 l, \ 28 +\ 0. d, 0. d, 2 l, \ 3c + h# ffff0000. d, h# 10000. d, 2 l, \ 40 +here memdescs - constant /memdescs + +: system-memory-map ( -- ) + caller-regs >rm-edx @ caller-regs >rm-eax ! + caller-regs >rm-ebx @ ?dup 0= if + memory-limit h# 100000 - memdescs h# 30 + l! +\ memory-limit memdescs h# 3c + l! +\ allmem memory-limit - memdescs h# 44 + l! + memdescs + then ( adr ) + + dup memdescs /memdescs + = if + drop + 0 caller-regs >rm-ecx ! + exit + then + + dup caller-regs >rm-edi w@ caller-regs >rm-es w@ seg:off> ( adr dst ) + caller-regs >rm-ecx @ move ( adr ) + caller-regs >rm-ecx @ + caller-regs >rm-ebx ! ( ) \ Continuation + rm-clr-cf +; + : bigmem-int ( -- ) rm-clr-cf rm-al@ case h# 01 of bigmem-16bit endof -\ h# 20 of system-memory-map endof + h# 20 of system-memory-map endof \ h# 81 of pm-system-memory-map endof ( default ) rm-set-cf ." Unsupported Bigmem int 15 AH=e8 AL=" dup . cr @@ -370,38 +619,94 @@ rm-set-cf h# 86 rm-ah! ;
-create sysconf 8 w, h# fc c, 1 c, 0 c, h# 70 c, 0 c, 0 c, +\ System configure +create sysconf + 8 w, \ 8 bytes following + h# fc c, \ model + 1 c, \ Submodel + 0 c, \ BIOS rev + h# 74 c, \ Feature - second 8259, RTC, INT 9 calls INT 15/4F, extended BIOS area + 0 c, + 0 c, + 0 c, + 0 c, + : get-conf ( -- ) sysconf 'rm-regs 8 move 'rm-regs >seg:off 0 caller-regs >rm-es w! rm-bx! + 0 rm-ax! ;
+: handle-mouse ( -- ) + rm-al@ case + 1 of rm-clr-cf endof \ Reset mouse + ( default ) ." Unsupported mouse INT 15 AH c2 AL " dup . cr rm-set-cf + endcase +; + : system-int ( -- ) \ INT 15 handler + rm-clr-cf rm-ah@ case + h# 91 of noshow 0 rm-ah! endof \ "pause" while waiting for I/O h# 53 of apm endof h# 86 of rm-dx@ rm-cx@ wljoin us endof \ Delay microseconds h# 8a of memory-limit h# 400.0000 - 0 max /1k lwsplit rm-dx! rm-ax! endof h# 88 of h# fffc rm-ax! endof \ Extended memory - at least 64 MB h# c0 of get-conf endof h# c1 of rm-set-cf h# 86 rm-ah! endof + h# c2 of handle-mouse endof h# e8 of bigmem-int endof ( default ) rm-set-cf ." Unsupported INT 15 AH=" dup . cr endcase ;
-: poll-key ( -- ) - key? if - key rm-al! 0 rm-ah! \ ASCII in AL, scancode in AH +h# 4800 value the-key + +: poll-key ( -- false | scan,ascii true ) + the-key ?dup if true exit then + 0 " get-scancode" kbd-ih $call-method if ( scancode ) + dup h# 80 and if ( scancode ) + \ Discard release events and escapes (e0) + drop false ( false ) + else + dup " scancode->char" kbd-ih $call-method 0= if 0 then ( scancode ascii ) + dup h# 80 and if drop 0 then \ Don't return e.g. 9B for arrows + swap bwjoin to the-key + the-key true + then + else + false + then +; + +0 value polled? +: poll-keystroke ( -- ) + noshow + polled? 0= if ." ? " then + true to polled? + poll-key if ( scancode,ascii ) + rm-ax! rm-flags@ h# 40 invert and rm-flags! else rm-flags@ h# 40 or rm-flags! then ; +: get-keystroke ( -- ) + noshow
-: keyboard-int ( -- ) \ INT 15 handler + begin poll-key until ( scancode,ascii ) + 0 to the-key + rm-ax! + + rm-al@ [char] q = if debug-me then + false to polled? +; + +: keyboard-int ( -- ) \ INT 16 handler rm-ah@ case - 1 of poll-key endof + 0 of get-keystroke endof + 1 of poll-keystroke endof 2 of 0 rm-al! endof \ Claim that no shift keys are active ( bit 7:sysrq 6:capslock 5:numlock 4:scrlock 3:ralt 2:rctrl 1:lalt 0:lctrl ) ( default ) ." Keyboard INT called with AH = " dup . cr @@ -417,9 +722,9 @@ h# 201 rm-bx! \ Version 2.1 1 rm-cl! \ Number of last PCI bus - XXX get this from PCI node ; -: pcibios ( -- ) +: pcibios ( -- ) \ INT 1a rm-clr-cf - rm-ah@ case + rm-al@ case h# 01 of pcibios-installed endof \ h# 02 of find-pci-device ( cx:devid dx:vendid si:index -> bh:bus# bl:devfn ) endof \ h# 03 of find-pci-class-code ( ecx:0,classcode si:index -> bh:bus# bl:devfn ) endof @@ -434,7 +739,7 @@ \ h# 0f of set-pci-int endof
( default ) h# 81 rm-ah! rm-set-cf - ." Unimplemented PCI BIOS INT - AH = " dup . cr + ." Unimplemented PCI BIOS INT 1a AH b1 - AL = " dup . cr endcase ;
@@ -445,30 +750,28 @@
: int-1a ( -- ) rm-ah@ case - h# 0 of get-timer-ticks endof + h# 0 of get-timer-ticks noshow endof h# b1 of pcibios endof - ( default ) ." Unimplemented INT 1a - AH = " dup . rm-set-cf + ( default ) ." Unimplemented INT 1a - AH = " dup . cr rm-set-cf endcase ;
-: showint - ." INT " 'rm-int w@ . ." AH " rm-ah@ . ." AL " rm-al@ . cr -; - : handle-bios-call ( -- ) + snap-int 'rm-int w@ case h# 10 of video-int endof h# 11 of sysinfo-int endof - h# 13 of disk-int endof -showint + h# 13 of noshow disk-int endof + h# 16 of keyboard-int endof + h# 15 of system-int endof h# 12 of h# a0000 /1k rm-ax! endof \ Low memory size - h# 15 of system-int endof - h# 16 of keyboard-int endof h# 1a of int-1a endof ( default ) ." Interrupt " dup . cr interact endcase + ?showint ; : rm-go ( -- ) + usb-quiet \ Load boot image at 7c00 h# 7c00 rm-init-program begin @@ -480,14 +783,14 @@ here xx - constant /xx : put-xx ( adr -- ) xx swap /xx move ; : get-mbr - " /ide@0" open-dev >r + " /pci/ide@0" open-dev >r h# 7c00 h# 3f 1 " read-blocks" r@ $call-method . r> close-dev ; : .lreg ( adr -- adr' ) 4 - dup l@ 9 u.r ; : .wreg ( adr -- adr' ) 2 - dup w@ 5 u.r ; : .caller-regs ( -- ) - ." AX CX BX DX SP BP SI DI" cr + ." AX CX DX BX SP BP SI DI" cr caller-regs >rm-eax 4 + 8 0 do .lreg loop cr cr ." DS ES FS GS PC FLAGS" cr