Files
TempleOS-Rijn/Kernel/KStart.CPP
T
2018-09-08 21:47:01 +02:00

375 lines
9.3 KiB
C++

asm {/*
See $LK,"::/Doc/Boot.TXT"$ for how booting works.
This file calls some BIOS routines before
switching to 32 bit, and then, 64 bit modes.
It continues here: $LK,"Kernel",A="FF:::/Kernel/KEnd.CPP,U0 Kernel"$.
The boot loader jumps here, in real-mode (16-bit).
It actually jumps to the $LK,"CBinFile",A="MN:CBinFile"$ which is placed
just before this $LK,"generated by the compiler",A="FF:::/Compiler/CMain.CPP,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,KStart:1"$
*/
USE16
SYS_KERNEL:: //This must match $LK,"CKernel",A="MN:CKernel"$.
JMP U16 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_PATCH_TABLE_BASE:: DU32 0;
SYS_RUN_LEVEL:: DU32 0;
#exe {StreamPrint("SYS_COMPILE_TIME:: DU64 0x%X;",Now);}
//See $LK,"BootDVDProve",A="MN:BootDVDProve"$
#assert SYS_COMPILE_TIME+sizeof(CDate)+sizeof(CBinFile)<DVD_BLK_SIZE
SYS_BOOT_BASE:: DU32 0; //Offset from start used by reboot
SYS_MEM_E801:: DU16 0,0;
SYS_MEM_E820:: DU8 MEM_NUM_E820_ENTRIES*MEM_E820_ENTRY_SIZE DUP (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.TXT"$ says just ring0.
GDT_CS64_RING3: DU64 0x0020FA0000000000,0; //$LK,"Ring3",A="FI:::/Demo/Lectures/Ring3.CPP"$, so you can play with.
GDT_DS: DU64 0x00CF92000000FFFF,0;
GDT_DS_RING3: DU64 0x00CFF2000000FFFF,0;
GDT_TR: DU8 MP_MAX_PROCESSORS*16 DUP(0);
GDT_TR_RING3: DU8 MP_MAX_PROCESSORS*16 DUP(0);
#assert $$-SYS_GDT==sizeof(CGDT)
SYS_GDT_PTR:: DU16 sizeof(CGDT)-1;
DU64 0;
SYS_PCI_BUSES:: DU16 0;
#assert $$-SYS_KERNEL==sizeof(CKernel)-sizeof(CBinFile)
//************************************
CORE0_16BIT_INIT::
//EBX is $LK,"SYS_BOOT_SRC",A="FF:::/Kernel/KStart.CPP,[SYS_BOOT_SRC]"$. (Val passed from boot blk, $LK,"BootHD",A="FF:::/Adam/Opt/Boot/BootHD.CPP,BOOT_SRC_HARDDRV"$, $LK,"BootDVD",A="FF:::/Adam/Opt/Boot/BootDVD.CPP,BOOT_SRC_DVD"$, & $LK,"BootRAM",A="FF:::/Adam/Opt/Boot/Reboot.CPP,BOOT_SRC_RAM"$.)
MOV AX,(BOOT_RAM_LIMIT-BOOT_STK_SIZE)/16
MOV SS,AX
MOV SP,BOOT_STK_SIZE
PUSH EBX //Will be $LK,"SYS_BOOT_SRC",A="FF:::/Kernel/KStart.CPP,[SYS_BOOT_SRC]"$. See $LK,"BootHD",A="FF:::/Adam/Opt/Boot/BootHD.CPP,BOOT_SRC_HARDDRV"$, $LK,"BootDVD",A="FF:::/Adam/Opt/Boot/BootDVD.CPP,BOOT_SRC_DVD"$ & $LK,"BootRAM",A="FF:::/Adam/Opt/Boot/Reboot.CPP,BOOT_SRC_RAM"$.
MOV AX,VGAM_TEXT/16
MOV ES,AX
MOV U32 ES:[0],'O'+BLUE<<12+('S'+GREEN<<12)<<16
CALL U16 GET_IP
GET_IP: POP BX
SUB BX,GET_IP
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 [SYS_MEM_E801],CX
MOV U16 [SYS_MEM_E801+2],DX
MOV CX,MEM_NUM_E820_ENTRIES-1 //Leave one to terminate
XOR EBX,EBX
MOV AX,DS
MOV ES,AX
MOV DI,SYS_MEM_E820
@@15: PUSH CX
MOV EAX,0xE820
MOV ECX,MEM_E820_ENTRY_SIZE
MOV EDX,'PAMS'
INT 0x15
JC @@20
CMP EAX,'PAMS'
JNE @@20
TEST EBX,EBX
JZ @@20
ADD DI,MEM_E820_ENTRY_SIZE
POP CX
LOOP @@15
JMP @@25
@@20: ADD SP,2
//Get PCI Bus Info
@@25: MOV U16 [SYS_PCI_BUSES],256
XOR DX,DX
MOV AX,0xB101
INT 0x1A
CMP DX,'PC'
JNE @@30
MOV CH,0
INC CX
MOV U16 [SYS_PCI_BUSES],CX
@@30:
CLI
//Enable A20
IN AL,0x92
OR AL,2
OUT 0x92,AL
POP U32 [SYS_BOOT_SRC] //See $LK,"BootHD",A="FF:::/Adam/Opt/Boot/BootHD.CPP,BOOT_SRC_HARDDRV"$, $LK,"BootDVD",A="FF:::/Adam/Opt/Boot/BootDVD.CPP,BOOT_SRC_DVD"$, & $LK,"BootRAM",A="FF:::/Adam/Opt/Boot/Reboot.CPP,BOOT_SRC_RAM"$.
CLD
XOR EAX,EAX
MOV AX,CS
MOV DS,AX
MOV ES,AX
SHL EAX,4
MOV U32 [SYS_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 for me to implement
16-bit mode in the assembler fully.
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
USE32
//************************************
// ASM Global vars not required for 16-bit start-up
ALIGN 8,OC_NOP
SYS_HEAP_BASE:: DU64 SYS_FIXED_AREA+sizeof(CSysFixedArea);
SYS_HEAP_LIMIT:: DU64 0;
#exe {
StreamPrint(
"SYS_MEM_INIT_FLAG:: DU8 %d;"
"SYS_MEM_INIT_VAL:: DU8 %d;"
"SYS_HEAP_INIT_FLAG:: DU8 %d;"
"SYS_HEAP_INIT_VAL:: DU8 %d;"
"SYS_VAR_INIT_FLAG:: DU8 %d;"
"SYS_VAR_INIT_VAL:: DU8 %d;",
kernel_cfg->opts[CFG_MEM_INIT], kernel_cfg->mem_init_val,
kernel_cfg->opts[CFG_HEAP_INIT],kernel_cfg->heap_init_val,
kernel_cfg->opts[CFG_VAR_INIT], kernel_cfg->var_init_val);
};
SYS_HEAP_DBG_FLAG:: DU8 _CFG_HEAP_DBG;
ALIGN 8,0
SYS_CTRL_ALT_FLAGS:: DU64 0;
SYS_EXTERN_TABLE:: DU64 0;
SYS_CODE_BP:: DU64 0;
SYS_DATA_BP:: DU64 0;
SYS_PROGRESSES::
SYS_PROGRESS1:: DU64 0;
SYS_PROGRESS1_MAX:: DU64 0;
SYS_PROGRESS1_DESC:: DU8 PROGRESS_DESC_LEN DUP(0);
SYS_PROGRESS2:: DU64 0;
SYS_PROGRESS2_MAX:: DU64 0;
SYS_PROGRESS2_DESC:: DU8 PROGRESS_DESC_LEN DUP(0);
SYS_PROGRESS3:: DU64 0;
SYS_PROGRESS3_MAX:: DU64 0;
SYS_PROGRESS3_DESC:: DU8 PROGRESS_DESC_LEN DUP(0);
SYS_PROGRESS4:: DU64 0;
SYS_PROGRESS4_MAX:: DU64 0;
SYS_PROGRESS4_DESC:: DU8 PROGRESS_DESC_LEN DUP(0);
#assert $$-SYS_PROGRESSES==sizeof(CProgress)*4
SYS_FOCUS_TASK:: DU64 0;
SYS_CPU_STRUCTS:: DU64 0;
SYS_MP_CNT:: DU64 1;
SYS_MP_CNT_INITIAL:: DU64 1;
SYS_MP_CNT_LOCK:: DU64 1;
ALIGN DFT_CACHE_LINE_WIDTH,OC_NOP
SYS_CACHE_LINE_WIDTH:: DU64 DFT_CACHE_LINE_WIDTH;
DU8 DFT_CACHE_LINE_WIDTH-sizeof(CBinFile)-8 DUP(0);
SYS_SEMAS:: DU8 NUM_SYS_SEMAS*SEMA_STRUCT_SIZE DUP(0);
//************************************
ALIGN 16,OC_NOP
CORE0_32BIT_INIT:: //Entry point for $LK,"RAMReboot",A="MN:RAMReboot"$.
PUSH U32 RFLAGG_START
POPFD
MOV EAX,SYS_START_CR0
MOV_CR0_EAX
MOV AX,CGDT.boot_ds //LOAD DS SELECTOR
MOV DS,AX
BTS U32 [SYS_RUN_LEVEL],RLf_32BIT
MOV ESI,U32 [SYS_BOOT_PATCH_TABLE_BASE]
MOV EDI,U32 [SYS_BOOT_BASE]
MOV AX,CGDT.ds
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
MOV SS,AX
MOV ESP,BOOT_RAM_LIMIT //Temp Stk
//Patch abs addresses
MOV ECX,U32 CPatchTableAbsAddr.abs_addres_cnt[ESI]
LEA ESI,U32 CPatchTableAbsAddr.abs_addres[ESI]
@@05: LODSD
ADD EAX,EDI
ADD U32 [EAX],EDI
LOOP @@05
DU8 0xEA; //JMP CGDT.cs32:@@10
DU32 @@10;
DU16 CGDT.cs32;
@@10: BTS U32 [SYS_RUN_LEVEL],RLf_PATCHED
CALL SYS_FIND_PCIBIOS_SERVICE_DIR
CALL SYS_FIND_PCI_SERVICES
MOV U32 [SYS_HEAP_BASE],SYS_FIXED_AREA+sizeof(CSysFixedArea)
CALL SYS_INIT_MEM
PUSH U32 0 //Return from next call will be 64-bit
CALL SYS_EM64T
USE64
BTS U32 [SYS_RUN_LEVEL],RLf_64BIT
FNINIT
MOV RAX,SYS_FIXED_AREA+CSysFixedArea.init_fpu_mmx
FXSAVE U64 [RAX]
//Init CPU0 Struct
PUSH SYS_FIXED_AREA+CSysFixedArea.adam
PUSH SYS_FIXED_AREA+CSysFixedArea.boot_cpu
PUSH 0
CALL &CPUStructInit
CALL SET_GS_BASE
//Init Adam HeapCtrl
MOV EDI,U32 SYS_FIXED_AREA+CSysFixedArea.adam_hc
MOV EAX,U32 SYS_FIXED_AREA+CSysFixedArea.adam_bp
MOV U64 CHeapCtrl.bp[RDI],RAX
MOV U32 CHeapCtrl.hc_signature[RDI],HEAP_CTRL_SIGNATURE_VAL
LEA RAX,U64 CHeapCtrl.next_um-CMemUsed.next[RDI]
MOV U64 CHeapCtrl.next_um[RDI],RAX
MOV U64 CHeapCtrl.last_um[RDI],RAX
MOV EAX,U32 SYS_FIXED_AREA+CSysFixedArea.adam
MOV U64 CHeapCtrl.mem_task[RDI],RAX
MOV U64 CTask.code_heap[RAX],RDI
MOV U64 CTask.data_heap[RAX],RDI
MOV U32 CTask.task_signature[RAX],TASK_SIGNATURE_VAL
BTS U32 [SYS_RUN_LEVEL],RLf_BOOT_HEAP
PUSH MEM_ADAM_STK
PUSH U32 SYS_FIXED_AREA+CSysFixedArea.adam
CALL &TaskInit
CALL SET_FS_BASE
MOV RSP,U64 CTask.rsp[RAX]
JMP I32 &KernelMain
//************************************
USE32
SYS_EM64T:: //Switch to long 64-bit mode
MOV_EAX_CR4
OR EAX,0xB0
MOV_CR4_EAX
MOV EAX,SYS_FIXED_AREA+CSysFixedArea.pml4
MOV_CR3_EAX
MOV ECX,IA32_EFER
XOR EDX,EDX
MOV EAX,IA32F_LME
WRMSR
MOV_EAX_CR0
BTS EAX,31 //enable paging (required for 64-bit mode)
MOV_CR0_EAX
DU8 0xEA; //JMP CGDT.cs64:@@05
DU32 @@05;
DU16 CGDT.cs64;
USE64
@@05: MOV AX,CGDT.ds
MOV DS,AX
MOV ES,AX
MOV SS,AX
MOV FS,AX
MOV GS,AX
RET
//************************************
SYS_RAM_REBOOT:: //This gets copied high. $LK,"SYS_RAM_REBOOT",A="FF:::/Adam/Opt/Boot/Reboot.CPP,SYS_RAM_REBOOT:2"$
PUSH U32 CGDT.ds //stk seg
PUSH U32 BOOT_RAM_LIMIT //stk
PUSH U32 0 //flags
PUSH U32 CGDT.cs32
LEA RAX,[@@10]
PUSH RAX
IRET
USE32
@@10: WBINVD
//disable paging
MOV_EAX_CR0
BTR EAX,31
MOV_CR0_EAX
MOV ECX,IA32_EFER
XOR EDX,EDX
XOR EAX,EAX
WRMSR
MOV EBX,BOOT_SRC_RAM
MOV EAX,I32 CORE0_32BIT_INIT
JMP EAX
SYS_RAM_REBOOT_END::
USE64
}