1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
[BITS 16]
[ORG 0]
START:
;; initialize segments
mov ax, BOOT1SEG
mov ds, ax
mov es, ax
mov ss, ax
;; make sure we are running on a 386+
;; while we're still in real mode, detect system hardware via BIOS
call PROBE_VIDEO
call GET_EQUIPMENT_LIST
call GET_MEMORY_SIZE
call GET_TIME
;; switch the processor into protected mode, keep ints disabled
cli
lidt [IDT_Pointer]
lgdt [GDT_Pointer]
call ENABLE_A20
mov ax, 0x01
lmsw ax
;; Jump to 32 bit code, this completes the transition to protected mode
db 0x66 ; operand size override prefix
db 0xea ; jmp opcode
dd (BOOT1SEG<<4) + setup_32 ; want to jump here
dw (1<<3) ; ...in the kernel code segment
[BITS 32]
setup_32:
;; set up data segment registers
mov ax, (2<<3)
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
;; create an initial stack
mov esp, KERN_STACK + 4096
mov ebp, esp
;; create a stack frame, pass ptr to hardware block as param
mov eax, (BOOT1SEG<<4)+BIOS_HARDWARE_BLOCK
push eax
push (BOOT1SEG<<4)+.HANG
jmp (1<<3):0x00010000 ; entry point of kernel
.HANG:
nop
jmp .HANG
; Setup data
; ----------------------------------------------------------------------
BIOS_HARDWARE_BLOCK:
bDisplayType db 0x00
bFontSize db 0x00
wEquipmentBitvector dw 0x0000
wMemorySize dw 0x0000
wSystemClock dw 0x0000
NUM_GDT_ENTRIES equ 3 ; number of entries in GDT
GDT_ENTRY_SZ equ 8 ; size of a single GDT entry
align 8, db 0
GDT:
; Descriptor 0 is not used
dw 0
dw 0
dw 0
dw 0
; Descriptor 1: kernel code segment
dw 0xFFFF ; bytes 0 and 1 of segment size
dw 0x0000 ; bytes 0 and 1 of segment base address
db 0x00 ; byte 2 of segment base address
db 0x9A ; present, DPL=0, non-system, code, non-conforming,
; readable, not accessed
db 0xCF ; granularity=page, 32 bit code, upper nibble of size
db 0x00 ; byte 3 of segment base address
; Descriptor 2: kernel data and stack segment
; NOTE: what Intel calls an "expand-up" segment
; actually means that the stack will grow DOWN,
; towards lower memory. So, we can use this descriptor
; for both data and stack references.
dw 0xFFFF ; bytes 0 and 1 of segment size
dw 0x0000 ; bytes 0 and 1 of segment base address
db 0x00 ; byte 2 of segment base address
db 0x92 ; present, DPL=0, non-system, data, expand-up,
; writable, not accessed
db 0xCF ; granularity=page, big, upper nibble of size
db 0x00 ; byte 3 of segment base address
GDT_Pointer:
dw NUM_GDT_ENTRIES*GDT_ENTRY_SZ ; limit
dd (BOOT1SEG<<4) + GDT ; base address
IDT_Pointer:
dw 0
dd 00
%include "defs.asm"
%include "hardware.asm"
%include "video.asm"
|