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)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 }