62
62
! ...
63
63
! 0x1e2: part_offset long Sector offset of booted MBR partition
64
64
! 0x1e6: elks_magic long "ELKS", written by build tool
65
- | 0x1ea: xms_kbytes word Size of XMS memory in Kbytes
66
- ! 0x1ea-0x1ee: 5 bytes UNUSED
65
+ ! 0x1ea: xms_kbytes word size of xms memory in kbytes
66
+ ! 0x1ec: hma_kernel byte hma=kernel seen in /bootopts
67
+ ! 0x1ed-0x1ee: 2 bytes UNUSED
67
68
! 0x1ef: SETUPSEG word UNUSED
68
69
! 0x1f1: setup_sects byte in 512-byte sectors, written by build tool
69
70
! 0x1f2: ROOTFLAGS word UNUSED
81
82
#include <linuxmt/boot.h>
82
83
83
84
// Relocating loader debug option
84
- // NOTE: If running the kernel in HMA, setup hangs when jumping to the kernel if
85
- // debug_output is active and serial_output is NOT active.
86
85
debug_output = 0 // display various register values during execution
87
86
serial_output = 0 // use INT 14 serial instead of INT 10 console out
88
87
debug_loader = 0 // display relocations
@@ -481,11 +480,11 @@ sys_hdr_msg:
481
480
482
481
sys_hdr_good:
483
482
mov %sp ,%bp
484
- mov 8 ,%dx // -2(%bp) code ( text) size
483
+ mov 8 ,%dx // -2(%bp) . text code size
485
484
push %dx
486
485
add $15 ,%dx // align on next paragraph (issue #209)
487
486
mov $4 ,%cl
488
- shr %cl ,%dx // DX = code size in paragraph
487
+ shr %cl ,%dx // DX = code size in paragraphs
489
488
shr %cl ,%bx // BX = header size in paragraphs
490
489
491
490
mov 12 ,%ax // -4(%bp) data size
@@ -512,49 +511,31 @@ sys_hdr_good:
512
511
add %bx ,%ax // skip header
513
512
mov %ax ,%ds
514
513
xor %si ,%si
514
+ xor %di ,%di
515
515
516
- push %ds
517
- mov $SETUP_DATA,%ax
518
- mov %ax ,%ds
519
- mov $0x8800 ,%ax
520
- int $0x15 // get xms size
521
- jc no_xms
522
- mov %ax ,(xms_kbytes)
523
- pop %ds
524
- #ifdef CONFIG_HMA_KERNEL
525
- cmp $64 ,%ax
526
- jl no_xms
527
- mov $0x2401 ,%ax
528
- int $0x15 // Set a20
529
- jnc 2f
530
- call set_a20
531
- call verify_a20
532
- jc no_xms
533
- 2:
516
+ #ifdef CONFIG_ARCH_IBMPC
517
+ // Check whether relocating .text to HMA is possible
518
+ call checkhma
519
+ jc 2f // no HMA
534
520
mov $HMA_SEG,%ax
535
521
jmp 1f
536
522
#endif
537
- no_xms:
538
- movw $0 ,(xms_kbytes)
539
- pop %ds
540
- mov $REL_SYSSEG,%ax
541
- 1:
542
- mov %ax ,%es
523
+ 2: mov $REL_SYSSEG,%ax
524
+ 1: mov %ax ,%es
543
525
mov %ax ,-18 (%bp ) // save .text segment
544
526
.ifeq debug_output
545
527
call hex4sp
546
528
.endif
547
529
548
- add %dx ,%ax // add code paragraphs = .fartext start
549
- #ifdef CONFIG_HMA_KERNEL
550
- jnc 1f // skip if it didn't overflow (no HMA)
551
- movw $REL_SYSSEG,%ax // .fartext start here
552
- 1:
553
- #endif
554
- mov %ax ,-20 (%bp ) // save .data start in case no .fartext
555
- xor %di ,%di
556
-
557
530
mov -2 (%bp ),%cx // code size in bytes
531
+ add %dx ,%ax // add code paragraphs = .fartext start
532
+ jnc 1f // skip if didn't overflow (no HMA)
533
+ mov $REL_SYSSEG,%ax // .fartext starts at normal .text location
534
+ add $16 ,%si // skip first paragraph at FFFF:0000
535
+ add $16 ,%di
536
+ sub $16 ,%cx
537
+ 1: mov %ax ,-20 (%bp ) // save .data start in case no .fartext
538
+
558
539
.hex4sp %ds ,"\nCopy DEF_SYSSEG .text to REL_SYSSEG DS:"
559
540
.hex4sp %si ,"SI:"
560
541
.hex4sp %es ,"ES:"
@@ -594,12 +575,9 @@ no_xms:
594
575
595
576
mov -18 (%bp ),%ax // kernel .text segment
596
577
add %dx ,%ax // skip code paragraphs
597
- #ifdef CONFIG_HMA_KERNEL
598
578
jnc 1f
599
- mov $REL_SYSSEG,%ax // if text in HMA, start fartext here
600
- #endif
601
- 1:
602
- mov %ax ,%es
579
+ mov $REL_SYSSEG,%ax // if text in HMA, start fartext here
580
+ 1: mov %ax ,%es
603
581
mov %ax ,-20 (%bp ) // save .fartext segment
604
582
xor %di ,%di
605
583
@@ -735,7 +713,7 @@ data_reloc:
735
713
.hex4sp %cx ,"entry:"
736
714
.if debug_output
737
715
.ifeq serial_output // if not serial output
738
- mov $debug_prompt, %ax
716
+ mov $debug_prompt,%ax
739
717
call csputs
740
718
xor %ah ,%ah // read key press
741
719
int $0x16
@@ -839,6 +817,9 @@ csputs: push %bx
839
817
jmp 1b
840
818
2: pop %bx
841
819
ret
820
+
821
+ debug_prompt:
822
+ .ascii "\r\nPress key to boot: \0"
842
823
.endif
843
824
844
825
// Output hex nibble, byte and word. All registers saved.
@@ -883,11 +864,7 @@ hex4sp: call hex4
883
864
ret
884
865
885
866
hello_mess:
886
- .ascii "\r\nTLVC Setup \0"
887
- .if debug_output
888
- debug_prompt:
889
- .ascii "\r\nPress key to boot: \0"
890
- .endif
867
+ .ascii "\r\nELKS Setup \0"
891
868
892
869
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
893
870
// Architecture specific routines for IBM PC
@@ -906,89 +883,6 @@ arch_get_mem:
906
883
#endif
907
884
ret
908
885
909
- // A20 handlers - from unreal.c
910
- // Even quite modern BIOSes don't support the A20 INT15 calls (QEMU does)
911
- // set_a20: Attempt to set the A20 line on 286 and higher
912
- // verify_a20: Check that a20 is set/working
913
-
914
- #ifdef CONFIG_HMA_KERNEL
915
- set_a20:
916
- pushf # save interrupt status
917
- cli # interrupts off
918
- call empty_8042
919
- mov $0xD0 ,%al # 8042 command byte to read output port
920
- out %al ,$0x64
921
- 1: in $0x64 ,%al
922
- test $1 ,%al # output buffer (data _from_ keyboard) full?
923
- jz 1b # no, loop
924
-
925
- in $0x60 ,%al # read output port
926
- or %ah ,%ah
927
- jne 2f
928
- and $0xFD ,%al # AND ~2 to disable
929
- jmp 3f
930
- 2: or $2 ,%al # OR 2 to enable
931
- 3: mov %al ,%ah
932
-
933
- call empty_8042
934
- mov $0xD1 ,%al # 8042 command byte to write output port
935
- out %al ,$0x64
936
-
937
- call empty_8042
938
- mov %ah ,%al # the value to write
939
- out %al ,$0x60
940
-
941
- call empty_8042
942
- popf # restore interrupt status
943
- ret
944
-
945
- 0: jmp 1f # a delay (probably not effective nor necessary)
946
- 1: jmp 2f
947
- 2: in $0x60 ,%al # read and discard data/status from 8042
948
- empty_8042:
949
- jmp 1f
950
- 1: jmp 2f # delay
951
- 2: in $0x64 ,%al
952
- test $1 ,%al # output buffer (data _from_ keyboard) full?
953
- jnz 0b # yes, read and discard
954
- test $2 ,%al # input buffer (data _to_ keyboard) empty?
955
- jnz empty_8042 # no, loop
956
- ret
957
-
958
- // verify if A20 gate is enabled, return 0 if disabled
959
- verify_a20:
960
- push %ds
961
- push %es
962
-
963
- xor %ax ,%ax
964
- mov %ax ,%ds
965
- dec %ax
966
- mov %ax ,%es
967
-
968
- pushf # save interrupt status
969
- cli # interrupts off
970
-
971
- mov %es :0x10 ,%ax # read word at FFFF:0010 (1 meg)
972
- not %ax # 1's complement
973
- pushw 0 # save word at 0000:0000 (0)
974
-
975
- mov %ax ,0 # word at 0 = ~(word at 1 meg)
976
- mov 0 ,%ax # read it back
977
- cmp %es :0x10 ,%ax # fail if word at 0 == word at 1 meg
978
-
979
- popw 0
980
-
981
- jz 1f # if ZF=1, the A20 gate is NOT enabled
982
- clc # no carry: OK
983
- 9: popf # restore interrupt status
984
- pop %es
985
- pop %ds
986
- ret
987
- 1: stc # Carry - error
988
- jmp 9b
989
-
990
- #endif
991
-
992
886
// Set INITSEG values for IBM PC
993
887
// Determine display type using INT 10h AH=12 and INT 10h AH=1A
994
888
// Get display page and mode using INT 10h AH=0F
@@ -1035,12 +929,72 @@ novga: mov %al,14 // CGA 25 rows
1035
929
mov %ax ,%ds
1036
930
call arch_get_mem // save base memory size
1037
931
mov %ax ,mem_kbytes
932
+ mov $0x8800 ,%ax // get xms size
933
+ int $0x15
934
+ jc 1f
935
+ mov %ax ,xms_kbytes
1038
936
1039
937
#ifdef CONFIG_BOOTOPTS
1040
938
call bootopts // load /bootopts into DEF_OPTSEG (0050:0000)
939
+ call hmabootopts // check /bootopts for hma=kernel
940
+ mov %al ,hma_kernel
1041
941
#endif
1042
942
ret
1043
943
944
+ // check for hma=kernel in /bootopts, return AX = 0 if not
945
+ hmabootopts:
946
+ push %ds
947
+ push %es
948
+
949
+ push %cs // ES = our code segment
950
+ pop %es
951
+ mov $DEF_OPTSEG,%ax // DS:SI = /bootopts in memory
952
+ mov %ax ,%ds
953
+
954
+ xor %si ,%si // look for hma=kernel in /bootopts segment
955
+ look: mov (%si ),%al // done when NUL seen
956
+ test %al ,%al
957
+ jz 1f
958
+ mov $hma_string,%di
959
+ mov $11 ,%cx
960
+ push %si
961
+ repz
962
+ cmpsb // %ds:(%si) with %es:(%di)
963
+ pop %si
964
+ inc %si
965
+ test %cx ,%cx
966
+ jnz look // NZ = no match
967
+ mov $'H',%ax
968
+ call putc
969
+ jmp 2f
970
+ 1: xor %ax ,%ax // no HMA
971
+ 2: pop %es
972
+ pop %ds
973
+ ret
974
+
975
+ hma_string:
976
+ .ascii "\nhma=kernel" // size = 11
977
+
978
+ // check whether HMA can be enabled, return NC if so with A20 enabled
979
+ checkhma:
980
+ push %ds
981
+ mov $INITSEG,%ax
982
+ mov %ax ,%ds
983
+ mov xms_kbytes,%ax //. must have xms size >= 64k
984
+ cmp $64 ,%ax
985
+ jl 1f
986
+ mov hma_kernel,%al // and hma=kernel in /bootopts
987
+ test %al ,%al
988
+ jz 1f
989
+ call enable_a20_gate // and A20 enabled
990
+ test %ax ,%ax
991
+ jz 1f
992
+ clc // success
993
+ jmp 2f
994
+ 1: stc // fail
995
+ 2: pop %ds
996
+ ret
997
+
1044
998
// Write AL to console, save all registers
1045
999
putc: push %ax
1046
1000
push %bx
@@ -1068,6 +1022,9 @@ putc: push %ax
1068
1022
// TODO: remove and use alternate mechanism for XT vs AT BIOS capabilities
1069
1023
#include "cputype.S"
1070
1024
1025
+ // include code to enable/verify A20 address gate
1026
+ #include "../lib/a20.inc"
1027
+
1071
1028
#endif /* CONFIG_ARCH_IBMPC*/
1072
1029
1073
1030
0 commit comments