asm {/* See ::/Doc/Boot.DD. TempleOS starts in real, calls some BIOS routines, switches to 32 bit, and 64 bit mode and continues in HolyC at KMain(). The boot loader jumps here in real-mode (16-bit). It actually jumps to the CBinFile header which is placed just before this by the compiler. 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. Kernel.PRJ */ USE16 SYS_KERNEL:: //This must match 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 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 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 Charter says just ring0. GDT_CS64_RING3: DU64 0x0020FA0000000000,0; //Ring3, 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:: //EAX is SYS_BOOT_SRC. (Val passed from boot blk, BootHD, BootDVD, & BootRAM.) MOV ECX,EAX MOV AX,(BOOT_RAM_LIMIT-BOOT_STK_SIZE)/16 MOV SS,AX MOV SP,BOOT_STK_SIZE PUSH ECX //Will be SYS_BOOT_SRC. See BootHD, BootDVD & BootRAM. 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] POP U32 [SYS_BOOT_SRC] //See BootHD, BootDVD, & BootRAM. 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 }