2020-02-15 20:01:48 +00:00
asm { /* See $LK,"::/Doc/Boot.DD"$.
2020-02-15 21:11:16 +00:00
ZenithOS starts in real , calls some BIOS
2020-02-15 20:01:48 +00:00
routines , switches to 32 bit , and 64 bit mode
and continues in $ LK , " HolyC " , A = " FI:::/Doc/HolyC.DD " $ at $ LK , " KMain " , A = " MN:KMain " $ ( ) .
The boot loader jumps here in real - mode ( 16 - bit ) .
It actually jumps to the $ LK , " CBinFile " , A = " MN:CBinFile " $ header which is
placed just before this by $ LK , " the compiler " , A = " FF:::/Compiler/CMain.HC,16 ALIGN " $ .
The header begins with a short jmp to
the start of this file ' s code which begins
with the following small jump past some data .
This file is first in the Kernel image
because it is # included first . $ LK , " Kernel.PRJ " , A = " FF:::/Kernel/Kernel.PRJ,KStart16:1 " $
*/
USE16
SYS_KERNEL : : //This must match $LK,"CKernel",A="MN:CKernel"$.
JMP I16 CORE0_16BIT_INIT
//************************************
// ASM Global vars required for 16-bit start-up
ALIGN 4 , OC_NOP
SYS_BOOT_SRC : : DU32 BOOT_SRC_NULL ;
SYS_BOOT_BLK : : DU32 0 ;
SYS_BOOT_PATCH_TABLE_BASE : : DU32 0 ;
SYS_RUN_LEVEL : : DU32 0 ;
# exe {StreamPrint("SYS_COMPILE_TIME:: DU64 0x%X;",Now);} //See $LK,"BootDVDProbe",A="MN:BootDVDProbe"$
# assert SYS_COMPILE_TIME+sizeof(CDate)+sizeof(CBinFile)<DVD_BLK_SIZE
MEM_BOOT_BASE : : DU32 0 ; //Offset from start used by reboot
MEM_E801 : : DU16 0 , 0 ;
MEM_E820 : : DU8 MEM_E820_ENTRIES_NUM * sizeof ( CMemE820 ) DUP ( 0 ) ;
MEM_PHYSICAL_SPACE : : DU64 0 ;
SYS_GDT_PTR : : DU16 sizeof ( CGDT ) - 1 ;
DU64 0 ;
SYS_PCI_BUSES : : DU16 0 ;
ALIGN 16 , OC_NOP
SYS_GDT : : //See $LK,"CGDT",A="MN:CGDT"$
GDT_NULL : DU64 0 , 0 ;
GDT_BOOT_DS : DU64 0x00CF92000000FFFF , 0 ; //Gets patched.
GDT_BOOT_CS : DU64 0x00CF9A000000FFFF , 0 ; //Gets patched.
GDT_CS32 : DU64 0x00CF9A000000FFFF , 0 ;
GDT_CS64 : DU64 0x00209A0000000000 , 0 ; //The $LK,"Charter",A="FI:::/Doc/Charter.DD"$ says just ring0.
GDT_CS64_RING3 : DU64 0x0020FA0000000000 , 0 ; //$LK,"Ring3",A="FI:::/Demo/Lectures/Ring3.HC"$, so you can play with.
GDT_DS : DU64 0x00CF92000000FFFF , 0 ;
GDT_DS_RING3 : DU64 0x00CFF2000000FFFF , 0 ;
GDT_TR : DU8 MP_PROCESSORS_NUM * 16 DUP ( 0 ) ;
GDT_TR_RING3 : DU8 MP_PROCESSORS_NUM * 16 DUP ( 0 ) ;
# assert $$-SYS_GDT==sizeof(CGDT)
# assert $$-SYS_KERNEL==sizeof(CKernel)-sizeof(CBinFile)
//************************************
CORE0_16BIT_INIT : :
2020-02-15 22:25:33 +00:00
//EAX is $LK,"SYS_BOOT_SRC",A="FF:::/Kernel/KStart16.HC,[SYS_BOOT_SRC]"$. (Val passed from boot blk, $LK,"BootHD",A="FF:::/Zenith/Boot/BootHD.HC,BOOT_SRC_HARDDRV"$, $LK,"BootDVD",A="FF:::/Zenith/Boot/BootDVD.HC,BOOT_SRC_DVD"$, & $LK,"BootRAM",A="FF:::/Zenith/Boot/BootRAM.HC,BOOT_SRC_RAM"$.)
2020-02-15 20:01:48 +00:00
MOV ECX , EAX
2020-02-16 01:19:05 +00:00
MOV AX , ( BOOT_RAM_LIMIT - BOOT_STACK_SIZE ) / 16
2020-02-15 20:01:48 +00:00
MOV SS , AX
2020-02-16 01:19:05 +00:00
MOV SP , BOOT_STACK_SIZE
2020-02-15 22:25:33 +00:00
PUSH ECX //Will be $LK,"SYS_BOOT_SRC",A="FF:::/Kernel/KStart16.HC,[SYS_BOOT_SRC]"$. See $LK,"BootHD",A="FF:::/Zenith/Boot/BootHD.HC,BOOT_SRC_HARDDRV"$, $LK,"BootDVD",A="FF:::/Zenith/Boot/BootDVD.HC,BOOT_SRC_DVD"$ & $LK,"BootRAM",A="FF:::/Zenith/Boot/BootRAM.HC,BOOT_SRC_RAM"$.
2020-02-15 20:01:48 +00:00
PUSH EBX
CALL U16 GET_RIP
GET_RIP : POP BX
SUB BX , GET_RIP
SHR BX , 4
MOV AX , CS
ADD AX , BX
PUSH AX
PUSH U16 @ @ 05
RETF
@ @ 05 : STI
MOV AX , CS
MOV DS , AX
MOV U32 [ SYS_RUN_LEVEL ] , RLF_16BIT
MOV AX , 0x4F02
MOV BX , 0x12 //640x480 16 color
# exe {
if ( ! kernel_cfg - > opts [ CFG_TEXT_MODE ] )
StreamPrint ( " INT 0x10 " ) ; //Enable VGA
} ;
CMP AX , 0x004F
JNE @ @ 10 //Jmp if fail
BTS U32 [ SYS_RUN_LEVEL ] , RLf_VGA
@ @ 10 :
//Get mem maps.
MOV AX , 0xE801
INT 0x15
MOV U16 [ MEM_E801 ] , CX
MOV U16 [ MEM_E801 + 2 ] , DX
MOV CX , MEM_E820_ENTRIES_NUM - 1 //Leave one to terminate
XOR EBX , EBX
MOV AX , DS
MOV ES , AX
MOV DI , MEM_E820
@ @ 15 : PUSH CX
MOV EAX , 0xE820
MOV ECX , sizeof ( CMemE820 )
MOV EDX , ' PAMS '
INT 0x15
JC @ @ 20
CMP EAX , ' PAMS '
JNE @ @ 20
TEST EBX , EBX
JZ @ @ 20
ADD DI , sizeof ( CMemE820 )
POP CX
LOOP @ @ 15
SUB SP , 2
@ @ 20 : ADD SP , 2
//Find how much space to map, start with E801 limit.
XOR EAX , EAX
MOV AX , [ MEM_E801 + 2 ]
SHL EAX , 16
ADD EAX , SYS_16MEG_AREA_LIMIT
XOR EDX , EDX
//Find max of E820 to set mapped space.
MOV SI , MEM_E820
@ @ 25 : MOV CL , CMemE820 . type [ SI ]
TEST CL , CL
JZ @ @ 35
MOV EBX , CMemE820 . base [ SI ]
MOV ECX , CMemE820 . base + 4 [ SI ]
ADD EBX , CMemE820 . len [ SI ]
ADC ECX , CMemE820 . len + 4 [ SI ]
SUB EBX , EAX
SBB ECX , EDX
JC @ @ 30
MOV EAX , CMemE820 . base [ SI ]
MOV EDX , CMemE820 . base + 4 [ SI ]
ADD EAX , CMemE820 . len [ SI ]
ADC EDX , CMemE820 . len + 4 [ SI ]
@ @ 30 : ADD SI , sizeof ( CMemE820 )
JMP @ @ 25
@ @ 35 : MOV [ MEM_PHYSICAL_SPACE ] , EAX
MOV [ MEM_PHYSICAL_SPACE + 4 ] , EDX
//Get PCI Bus Info
MOV U16 [ SYS_PCI_BUSES ] , 256
XOR DX , DX
MOV AX , 0xB101
INT 0x1A
CMP DX , ' PC '
JNE @ @ 40
MOV CH , 0
INC CX
MOV U16 [ SYS_PCI_BUSES ] , CX
@ @ 40 :
CLI
//Enable A20
IN AL , 0x92
OR AL , 2
OUT 0x92 , AL
POP U32 [ SYS_BOOT_BLK ]
2020-02-15 22:25:33 +00:00
POP U32 [ SYS_BOOT_SRC ] //See $LK,"BootHD",A="FF:::/Zenith/Boot/BootHD.HC,BOOT_SRC_HARDDRV"$, $LK,"BootDVD",A="FF:::/Zenith/Boot/BootDVD.HC,BOOT_SRC_DVD"$, & $LK,"BootRAM",A="FF:::/Zenith/Boot/BootRAM.HC,BOOT_SRC_RAM"$.
2020-02-15 20:01:48 +00:00
CLD
XOR EAX , EAX
MOV AX , CS
MOV DS , AX
MOV ES , AX
SHL EAX , 4
MOV U32 [ MEM_BOOT_BASE ] , EAX
MOV DX , CS
SUB DX , sizeof ( CBinFile ) / 16
# assert !(sizeof(CBinFile)&15)
MOV GS , DX
MOV EDX , EAX
ADD EDX , U32 GS : [ CBinFile . patch_table_offset ]
SUB EDX , sizeof ( CBinFile )
MOV U32 [ SYS_BOOT_PATCH_TABLE_BASE ] , EDX
ADD U32 [ GDT_BOOT_DS + 2 ] , EAX
ADD U32 [ GDT_BOOT_CS + 2 ] , EAX
ADD EAX , I32 SYS_GDT
MOV U32 [ SYS_GDT_PTR + CSysLimitBase . base ] , EAX
LGDT U32 [ SYS_GDT_PTR ]
MOV EAX , SYS_START_CR0
MOV_CR0_EAX
/* The assembler doesn't support far jumps so
we hand code it . 16 - bit code is not important
enough to fully implement in the assembler .
To complete the switch to 32 - bit mode , we have to load
the code segment with a far jump .
*/
DU8 0x66 , 0xEA ; //JMP CGDT.boot_cs:CORE0_32BIT_INIT
DU32 CORE0_32BIT_INIT ;
DU16 CGDT . boot_cs ;
# assert $$+16<=0xFFFF
}