375 lines
9.3 KiB
C++
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_PAGE_TABLES
|
|
|
|
PUSH U32 0 //Return from next call will be 64-bit
|
|
CALL SYS_ENTER_LONG_MODE
|
|
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_ENTER_LONG_MODE:: //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
|
|
}
|