summaryrefslogtreecommitdiffstats
path: root/src/arch/i386/prefix/lmelf_prefix.S
blob: 3c1e7251db219f04ba067cefa53b076eb57c94d2 (plain) (blame)
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include "elf.h"
	.arch sledgehammer
	.code32
	.equ	FLAT_CODE_SEG,_pmcs-_gdt
	.equ	FLAT_DATA_SEG,_pmds-_gdt
	.equ	MSR_K6_EFER,   0xC0000080
	.equ	EFER_LME,      0x00000100
	.equ	X86_CR4_PAE,   0x00000020
	.equ	CR0_PG,        0x80000000

	.section ".prefix", "ax", @progbits

#define LOAD_ADDR 0x10000
		
	/* ELF Header */
	.globl elf_header
elf_header:	
e_ident:	.byte	0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
e_type:		.short	ET_EXEC
e_machine:	.short	EM_X86_64
e_version:	.long	1
e_entry:	.long	LOAD_ADDR + elf_start - elf_header
e_phoff:	.long	elf_program_header - elf_header
e_shoff:	.long	0
e_flags:	.long	0
e_ehsize:	.short	elf_header_end - elf_header
e_phentsize:	.short	ELF32_PHDR_SIZE
e_phnum:	.short	(elf_program_header_end - elf_program_header)/ELF32_PHDR_SIZE
e_shentsize:	.short	0
e_shnum:	.short	0
e_shstrndx:	.short	0
elf_header_end:
	
elf_program_header:
phdr1_p_type:	.long	PT_NOTE
phdr1_p_offset:	.long	elf_note - elf_header
phdr1_p_vaddr:	.long	elf_note
phdr1_p_paddr:	.long	elf_note
phdr1_p_filesz:	.long	elf_note_end - elf_note
phdr1_p_memsz:	.long	elf_note_end - elf_note
phdr1_p_flags:	.long	PF_R | PF_W | PF_X
phdr1_p_align:	.long	0

/* The decompressor */
phdr2_p_type:	.long	PT_LOAD
phdr2_p_offset:	.long	0
phdr2_p_vaddr:	.long	elf_header
phdr2_p_paddr:	.long	LOAD_ADDR
phdr2_p_filesz:	.long	_verbatim_size
phdr2_p_memsz:	.long	_image_size
phdr2_p_flags:	.long	PF_R | PF_W | PF_X
phdr2_p_align:	.long	16

elf_program_header_end:

	.globl elf_note
elf_note:
	.balign 4
	.int 2f - 1f
	.int 4f - 3f
	.int EIN_PROGRAM_NAME
1:	.asciz "ELFBoot"
2:
	.balign 4
3:	
	.asciz "Etherboot"
4:


	.balign 4
	.int 2f - 1f
	.int 4f - 3f
	.int EIN_PROGRAM_VERSION
1:	.asciz "ELFBoot"
2:
	.balign 4
3:	
	.asciz VERSION
4:

#if 0
	.balign 4
	.int 2f - 1f
	.int 4f - 3f
	.int EIN_PROGRAM_CHECKSUM
1:	.asciz "ELFBoot"
2:
	.balign 4
3:	
	.word 0
4:
#endif
	.balign 4
elf_note_end:

elf_start:
	.code64
	/* Reload the gdt to something I know */
	leaq	_gdt(%rip), %rax
	movq	%rax, 0x02 + gdtptr(%rip)
	lgdt	gdtptr(%rip)

	/* Enter 32bit compatibility mode */
	leaq	elf_start32(%rip), %rax
	movl	%eax, 0x00 + elf_start32_addr(%rip)
	ljmp	*elf_start32_addr(%rip)

elf_start32:	
	.code32
	/* Reload the data segments */
	movl	$FLAT_DATA_SEG, %eax
	movl	%eax, %ds
	movl	%eax, %es
	movl	%eax, %ss
	
	/* Disable paging */
	movl	%cr0, %eax
	andl	$~CR0_PG, %eax
	movl	%eax, %cr0

	/* Disable long mode */
	movl	$MSR_K6_EFER, %ecx
	rdmsr
	andl	$~EFER_LME, %eax
	wrmsr

	/* Disable PAE */
	movl	%cr4, %eax
	andl	$~X86_CR4_PAE, %eax
	movl	%eax, %cr4

	/* Save the first argument */
	pushl	%ebx
	jmp	_start

gdtptr:	
	.word	_gdt_end - _gdt -1
	.long	_gdt
	.long	0
_gdt:
elf_start32_addr:
	.long	elf_start32
	.long	FLAT_CODE_SEG
_pmcs:
	/* 32 bit protected mode code segment, base 0 */
	.word	0xffff,0
	.byte	0,0x9f,0xcf,0

_pmds:
	/* 32 bit protected mode data segment, base 0 */
	.word	0xffff,0
	.byte	0,0x93,0xcf,0
_gdt_end:	


	/* Dummy routines to satisfy the build */
	.section ".text16", "ax", @progbits
prefix_exit:

prefix_exit_end:
	.previous