-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathboot_x86.asm
More file actions
204 lines (200 loc) · 8.69 KB
/
boot_x86.asm
File metadata and controls
204 lines (200 loc) · 8.69 KB
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
;
; src/boot_x86.asm
; https://codeberg.org/bzt/easyboot
;
; Copyright (C) 2023 bzt
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;
; @brief Legacy mode Protective Master Boot Record for Easyboot, written with
; flatassembler: https://flatassembler.net It's job is to load loader_x86.efi,
; extract its sections, set up long mode and pass control to it
;
; Memory layout on handover:
; 0h - 400h IVT (must be preserved)
; 400h - 4FFh BDA (must be preserved)
; 4FFh - 500h BIOS boot drive code
; 500h - 510h BIOS LBA packet
; 510h - 550h GDT
; 550h - 1000h stack (2k+)
; 1000h - 8000h paging tables
; 8000h - 60000h loader_x86.efi's sections
; 9A000h - A0000h EBDA (must be preserved)
easyboot_addr equ 08000h
ORG 07C00h
USE16
;*********************************************************************
;* code *
;*********************************************************************
jmp short @f ; mandatory jump (magic)
nop
db "Easyboot", 0, 0, 0
;---- set up environment ----
@@: cli
cld
mov al, 0FFh ; disable PIC
out 021h, al
out 0A1h, al
in al, 70h ; disable NMI
or al, 80h
out 70h, al
xor ax, ax
mov ss, ax
mov ds, ax
mov es, ax
mov sp, easyboot_addr
;---- read in loader_x86.efi ----
mov bx, 500h
mov di, bx
mov byte [di - 1], dl
mov si, loader_lba
xor ah, ah
mov al, 16 ; size
stosw
mov al, 120 ; count
stosw
xor ax, ax ; addr0, load to 60000h
stosw
mov ah, 60h ; addr1
stosw
movsw ; sect0
movsw ; sect1
xor ax, ax
stosw ; sect2
stosw ; sect3
mov si, GDT_value
mov cx, word[si]
repnz movsb
mov ah, 42h
mov si, bx
push si
int 13h
pop si
add byte [si + 7], 15
add dword [si + 8], 120
mov ah, 42h
int 13h
;---- enable protmode ----
mov ax, 2401h ; enable A20
int 15h
lgdt [510h]
mov eax, cr0
or al, 1
mov cr0, eax
jmp 16:@f
USE32
@@: mov ax, 24
mov ds, ax
mov es, ax
; look for long mode supported flag
xor edx, edx
mov eax, 80000001h
cpuid
bt edx, 29
jnc .die
;---- enable longmode ----
xor eax, eax
mov ah, 010h
mov cr3, eax
; we only map 2M here, loader will finish up the rest overwriting us in the process
mov edx, eax ; PML4
mov ebx, eax
xor eax, eax
mov dword [ebx], 02003h ; pointer to 2M PDPE
mov dword [ebx + 4], eax
add ebx, edx ; 2M PDPE
mov dword [ebx], 03003h
mov dword [ebx + 4], eax
add ebx, edx ; 2M PDE
mov dword [ebx], 00083h
mov dword [ebx + 4], eax
mov al, 0E0h ; set PAE, MCE, PGE; clear everything else
mov cr4, eax
mov ecx, 0C0000080h ; EFER MSR
rdmsr
bts eax, 8 ; enable long mode page tables
wrmsr
mov eax, cr0
xor cl, cl
or eax, ecx
btc eax, 16 ; clear WP
mov cr0, eax ; enable paging with cache disabled (set PE, CD)
lgdt [510h] ; read 80 bit address (16+64)
jmp 32:@f
USE64
@@: xor rax, rax ; load long mode segments
mov al, 40
mov ds, ax
mov es, ax
mov ss, ax
mov ax, easyboot_addr
;---- parse loader_x86.efi (PE / COFF format) ----
mov ebx, 60000h ; load buffer address
cmp word [ebx], 5A4Dh ; check MZ
jne .die
mov r8d, ebx
add ebx, dword [ebx + 0x3c] ; get COFF header
cmp word [ebx], 4550h ; check PE
jne .die
mov dl, byte [ebx + 6] ; number of sections
mov r9d, dword [ebx + 0x28] ; entry point
mov ebp, dword [ebx + 0x2c] ; code base
add r9d, eax
sub r9d, ebp
add bx, word [ebx + 0x14] ; add header size
add bx, 24 ; ebx now points to section table
@@: mov edi, dword [ebx + 12] ; copy sections from PE into VA
add edi, eax
sub edi, ebp ; dest: virtual address + reloc offset - code base
mov ecx, dword [ebx + 16] ; size of raw data
mov esi, dword [ebx + 20]
add esi, r8d ; source: pointer to raw data + load offset
repnz movsb
add ebx, 40 ; go to next section
dec dl
jnz @b
xor rsp, rsp
mov sp, 1000h ; set stack
xor rcx, rcx ; image handle
xor rdx, rdx ; system table pointer
jmp r9 ; jump to relocated entry point
;---- die function ----
; written in a way that it's decodeable as prot mode as well as long mode instructions
.die: mov esi, .err
mov edi, 0B8000h
mov ah, 04fh
@@: lodsb
or al, al
jz @f
stosw
jmp @b
@@: hlt
;*********************************************************************
;* data area *
;*********************************************************************
.err: db "PMBR-ERR", 0
GDT_value: dw GDT_value.end-GDT_value ; value / null descriptor
dd 510h
dw 0
dd 0000FFFFh,00009800h ; 8 - legacy real cs
dd 0000FFFFh,00CF9A00h ; 16 - prot mode cs
dd 0000FFFFh,008F9200h ; 24 - prot mode ds
dd 0000FFFFh,00AF9A00h ; 32 - long mode cs
dd 0000FFFFh,00CF9200h ; 40 - long mode ds
.end: db 01B0h-($-$$) dup 0
loader_lba: dd 0h ; the image generator sets this
;---- space for legacy partitioning table ----
db 01FEh-($-$$) dup 0
db 55h, 0AAh ; mandatory magic bytes