Files
x86-bare-metal-examples/intel-protected/startup.asm
Ciro Santilli fb3c7e04c4 Move all documentation to README.adoc
This includes both separate .md files, and documentation that was on the
head of the .S source files.

Retest everything as this was done, and fix a few easy things.
2018-05-13 22:13:19 +01:00

394 lines
6.6 KiB
NASM
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; TODO finish converting this to a text file that looks like the PDF...
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; ASSUMPTIONS:
;
; 1. The bottom 64K of memory is ram, and can be used for
; scratch space by this module.
;
; 2. The system has sufficient free usable ram to copy the
; initial GDT, IDT, and TSS
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; configuration data - must match with build definition
CS_BASE EQU 0FFFF0000H
; CS_BASE is the linear address of the segment STARTUP_CODE
; - this is specified in the build language file
RAM_START EQU 400H
; RAM_START is the start of free, usable ram in the linear
; memory space. The GDT, IDT, and initial TSS will be
; copied above this space, and a small data segment will be
; discarded at this linear address. The 32-bit word at
; RAM_START will contain the linear address of the first
; free byte above the copied tables - this may be useful if
; a memory manager is used.
TSS_INDEX EQU 10
; TSS_INDEX is the index of the TSS of the first task to
; run after startup
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ------------------------- STRUCTURES and EQU ---------------
; structures for system data
; TSS structure
TASK_STATE STRUC
link DW ?
link_h DW ?
ESP0 DD ?
SS0 DW ?
SS0_h DW ?
ESP1 DD ?
SS1 DW ?
SS1_h DW ?
ESP2 DD ?
SS2 DW ?
SS2_h DW ?
CR3_reg DD ?
EIP_reg DD ?
EFLAGS_regDD ?
EAX_reg DD ?
ECX_reg DD ?
EDX_reg DD ?
EBX_reg DD ?
ESP_reg DD ?
EBP_reg DD ?
ESI_reg DD ?
EDI_reg DD ?
ES_reg DW ?
ES_h DW ?
CS_reg DW ?
CS_h DW ?
SS_reg DW ?
SS_h DW ?
DS_reg DW ?
DS_h DW ?
FS_reg DW ?
FS_h DW ?
GS_reg DW ?
GS_h DW ?
LDT_reg DW ?
LDT_h DW ?
TRAP_reg DW ?
IO_map_baseDW ?
TASK_STATE ENDS
; basic structure of a descriptor
DESC STRUC
lim_0_15 DW ?
bas_0_15 DW ?
bas_16_23 DB ?
access DB ?
gran DB ?
bas_24_31 DB ?
DESC ENDS
; structure for use with LGDT and LIDT instructions
TABLE_REG STRUC
table_lim DW ?
table_linearDD ?
TABLE_REG
ENDS
; offset of GDT and IDT descriptors in builder generated GDT
GDT_DESC_OFF
EQU 1*SIZE(DESC)
IDT_DESC_OFF
EQU 2*SIZE(DESC)
; equates for building temporary GDT in RAM
LINEAR_SEL
EQU
1*SIZE (DESC)
LINEAR_PROTO_LO
EQU
00000FFFFH ; LINEAR_ALIAS
LINEAR_PROTO_HI
EQU
000CF9200H
; Protection Enable Bit in CR0
PE_BIT EQU 1B
; ------------------------------------------------------------
; ------------------------- DATA SEGMENT----------------------
; Initially, this data segment starts at linear 0, according
; to the processors power-up state.
STARTUP_DATA
SEGMENT RW
free_mem_linear_base
LABEL
DWORD
TEMP_GDT
LABEL
BYTE ; must be first in segment
TEMP_GDT_NULL_DESC
DESC
<>
TEMP_GDT_LINEAR_DESC DESC
<>
; scratch areas for LGDT and
LIDT instructions
TEMP_GDT_SCRATCH TABLE_REG
<>
APP_GDT_RAM
TABLE_REG
<>
APP_IDT_RAM
TABLE_REG
<>
; align end_data
fill
DW
?
; last thing in this segment - should be on a dword boundary
end_data
LABEL
BYTE
STARTUP_DATA
ENDS
; ------------------------------------------------------------
; ------------------------- CODE SEGMENT----------------------
STARTUP_CODE SEGMENT ER PUBLIC USE16
; filled in by builder
PUBLIC GDT_EPROM
GDT_EPROM
TABLE_REG
<>
; filled in by builder
PUBLIC IDT_EPROM
IDT_EPROM
TABLE_REG
<>
; entry point into startup code - the bootstrap will vector
; here with a near JMP generated by the builder.
This
; label must be in the top 64K of linear memory.
PUBLIC
STARTUP
STARTUP:
; DS,ES address the bottom 64K of flat linear memory
ASSUME DS:STARTUP_DATA, ES:STARTUP_DATA
; See Figure 9-4
; load GDTR with temporary GDT
LEA
EBX,TEMP_GDT ; build the TEMP_GDT in low ram,
MOV
DWORD PTR [EBX],0
; where we can address
MOV
DWORD PTR [EBX]+4,0
MOV
DWORD PTR [EBX]+8, LINEAR_PROTO_LO
MOV
DWORD PTR [EBX]+12, LINEAR_PROTO_HI
MOV
TEMP_GDT_scratch.table_linear,EBX
MOV
TEMP_GDT_scratch.table_lim,15
DB 66H; execute a 32 bit LGDT
LGDT
TEMP_GDT_scratch
; enter protected mode
MOV
EBX,CR0
OR
EBX,PE_BIT
MOV
CR0,EBX
; clear prefetch queue
JMP
CLEAR_LABEL
CLEAR_LABEL:
; make DS and ES address 4G of linear memory
MOV
CX,LINEAR_SEL
MOV
DS,CX
MOV
ES,CX
; do board specific initialization
;
;
; ......
;
; See Figure 9-5
; copy EPROM GDT to ram at:
;
RAM_START + size (STARTUP_DATA)
MOV
EAX,RAM_START
ADD
EAX,OFFSET (end_data)
MOV
EBX,RAM_START
MOV
ECX, CS_BASE
ADD
ECX, OFFSET (GDT_EPROM)
MOV
ESI, [ECX].table_linear
MOV
EDI,EAX
MOVZX
ECX, [ECX].table_lim
MOV
APP_GDT_ram[EBX].table_lim,CX
INC
ECX
MOV
EDX,EAX
MOV
APP_GDT_ram[EBX].table_linear,EAX
ADD
EAX,ECX
REP MOVS
BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
; fixup
GDT base in descriptor
MOV
ECX,EDX
MOV
[EDX].bas_0_15+GDT_DESC_OFF,CX
ROR
ECX,16
; PAGE 4 TODO remove later.
MOV
[EDX].bas_16_23+GDT_DESC_OFF,CL
[EDX].bas_24_31+GDT_DESC_OFF,CH
; copy EPROM IDT to ram at:
; RAM_START+size(STARTUP_DATA)+SIZE (EPROM GDT)
MOV
ECX, CS_BASE
ADD
ECX, OFFSET (IDT_EPROM)
MOV
ESI, [ECX].table_linear
MOV
EDI,EAX
MOVZX
ECX, [ECX].table_lim
MOV
APP_IDT_ram[EBX].table_lim,CX
INC
ECX
MOV
APP_IDT_ram[EBX].table_linear,EAX
MOV
EBX,EAX
ADD
EAX,ECX
REP MOVS
BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
MOV
ROR
MOV
MOV
MOV
LGDT
LIDT
REPMOV
MOV
MOV
MOV
MOV
MOV
ROL
MOV
MOV
LSL
INC
MOV
ADD
MOVS
MOV
ROL
MOV
MOV
ROL
;save start
MOV
; fixup IDT pointer in GDT
[EDX].bas_0_15+IDT_DESC_OFF,BX
EBX,16
[EDX].bas_16_23+IDT_DESC_OFF,BL
[EDX].bas_24_31+IDT_DESC_OFF,BH
; load GDTR and IDTR
EBX,RAM_START
DB
66H
; execute a 32 bit LGDT
APP_GDT_ram[EBX]
DB
66H
; execute a 32 bit LIDT
APP_IDT_ram[EBX]
; move the TSS
EDI,EAX
EBX,TSS_INDEX*SIZE(DESC)
ECX,GDT_DESC_OFF ;build linear address for TSS
GS,CX
DH,GS:[EBX].bas_24_31
DL,GS:[EBX].bas_16_23
EDX,16
DX,GS:[EBX].bas_0_15
ESI,EDX
ECX,EBX
ECX
EDX,EAX
EAX,ECX
BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
; fixup TSS pointer
GS:[EBX].bas_0_15,DX
EDX,16
GS:[EBX].bas_24_31,DH
GS:[EBX].bas_16_23,DL
EDX,16
of free ram at linear location RAMSTART
free_mem_linear_base+RAM_START,EAX
;assume no LDT used in the initial task - if necessary,
;code to move the LDT could be added, and should resemble
;that used to move the TSS
; load task register
LTR
BX
; No task switch, only descriptor loading
; See Figure 9-6
; load minimal set of registers necessary to simulate task
; switch
MOV
AX,[EDX].SS_reg
; start loading registers
MOV
EDI,[EDX].ESP_reg
MOV
SS,AX
MOV
ESP,EDI
; stack now valid
PUSH
DWORD PTR [EDX].EFLAGS_reg
PUSH
DWORD PTR [EDX].CS_reg
PUSH
DWORD PTR [EDX].EIP_reg
MOV
AX,[EDX].DS_reg
MOV
BX,[EDX].ES_reg
MOV
DS,AX
; DS and ES no longer linear memory
MOV
ES,BX
; simulate far jump to initial task
IRETD
STARTUP_CODE ENDS
END STARTUP, DS:STARTUP_DATA, SS:STARTUP_DATA