1+ ;;==============================================================================
2+ ;;
3+ ;;==============================================================================
4+
5+
6+ %include "./asm/include/sysvar.inc"
7+
8+ ;; tsl_ap.asm
9+ extern GDTR32
10+ extern tmpGDTR64 ;; Only for bios boot. See tsl.asm 1178 TO-DO.
11+ extern SYS64_CODE_SEL
12+
13+ extern start64
14+
15+
16+ ;; Primera parte: pasa real mode a protected mode.
17+
18+
19+
20+
21+
22+ BITS 16
23+
24+ start16:
25+
26+
27+
28+ ; Get the BIOS E820 Memory Map
29+ ; https://wiki.osdev.org/Detecting_Memory_(x86)#BIOS_Function:_INT_0x15,_EAX_=_0xE820
30+ ; The code below is from https://wiki.osdev.org/Detecting_Memory_(x86)#Getting_an_E820_Memory_Map
31+ ; inputs: es:di -> destination buffer for 24 byte entries
32+ ; outputs: bp = entry count, trashes all registers except esi
33+ ; The function below creates a memory map at address 0x6000 and the records are:
34+ ; 64-bit Base
35+ ; 64-bit Length
36+ ; 32-bit Type (1 = normal, 2 reserved, ACPI reclaimable)
37+ ; 32-bit ACPI
38+ ; 64-bit Padding
39+ do_e820:
40+ mov edi , 0x00006000 ; location that memory map will be stored to
41+ xor ebx , ebx ; ebx must be 0 to start
42+ xor bp , bp ; keep an entry count in bp
43+ mov edx , 0x0534D4150 ; Place "SMAP" into edx
44+ mov eax , 0xe820
45+ mov [ es : di + 20 ], dword 1 ; force a valid ACPI 3.X entry
46+ mov ecx , 24 ; ask for 24 bytes
47+ int 0x15
48+ jc nomemmap ; carry set on first call means "unsupported function"
49+ mov edx , 0x0534D4150 ; Some BIOSes apparently trash this register?
50+ cmp eax , edx ; on success, eax must have been reset to "SMAP"
51+ jne nomemmap
52+ test ebx , ebx ; ebx = 0 implies list is only 1 entry long (worthless)
53+ je nomemmap
54+ jmp jmpin
55+ e820lp:
56+ mov eax , 0xe820 ; eax, ecx get trashed on every int 0x15 call
57+ mov [ es : di + 20 ], dword 1 ; force a valid ACPI 3.X entry
58+ mov ecx , 24 ; ask for 24 bytes again
59+ int 0x15
60+ jc memmapend ; carry set means "end of list already reached"
61+ mov edx , 0x0534D4150 ; repair potentially trashed register
62+ jmpin:
63+ jcxz skipent ; skip any 0 length entries
64+ cmp cl , 20 ; got a 24 byte ACPI 3.X response?
65+ jbe notext
66+ test byte [ es : di + 20 ], 1 ; if so: is the "ignore this data" bit clear?
67+ je skipent
68+ notext:
69+ mov ecx , [ es : di + 8 ] ; get lower dword of memory region length
70+ test ecx , ecx ; is the qword == 0?
71+ jne goodent
72+ mov ecx , [ es : di + 12 ] ; get upper dword of memory region length
73+ jecxz skipent ; if length qword is 0, skip entry
74+ goodent:
75+ inc bp ; got a good entry: ++count, move to next storage spot
76+ add di , 32 ; Pad to 32 bytes for each record
77+ skipent:
78+ test ebx , ebx ; if ebx resets to 0, list is complete
79+ jne e820lp
80+ nomemmap:
81+ memmapend:
82+ xor eax , eax ; Create a blank record for termination (32 bytes)
83+ mov ecx , 8
84+ rep stosd
85+
86+ ; Enable the A20 gate
87+ set_A20:
88+ in al , 0x64
89+ test al , 0x02
90+ jnz set_A20
91+ mov al , 0xD1
92+ out 0x64 , al
93+ check_A20:
94+ in al , 0x64
95+ test al , 0x02
96+ jnz check_A20
97+ mov al , 0xDF
98+ out 0x60 , al
99+
100+ mov cx , 0x4000 - 1 ; Start looking from here
101+ VBESearch:
102+ inc cx
103+ mov bx , cx ; Mode is saved to BX for the set command later
104+ cmp cx , 0x5000
105+ je halt
106+ mov edi , VBEModeInfoBlock ; VBE data will be stored at this address
107+ mov ax , 0x4F01 ; VESA SuperVGA BIOS - GET SuperVGA MODE INFORMATION - http://www.ctyme.com/intr/rb-0274.htm
108+ int 0x10
109+ cmp ax , 0x004F ; Return value in AX should equal 0x004F if command supported and successful
110+ jne VBESearch ; Try next mode
111+ cmp byte [ VBEModeInfoBlock.BitsPerPixel ], 32 ; Desired bit depth
112+ jne VBESearch ; If not equal, try next mode
113+ cmp word [ VBEModeInfoBlock.XResolution ], Horizontal_Resolution ; Desired XRes here
114+ jne VBESearch
115+ cmp word [ VBEModeInfoBlock.YResolution ], Vertical_Resolution ; Desired YRes here
116+ jne VBESearch
117+ or bx , 0x4000 ; Use linear/flat frame buffer model (set bit 14)
118+ mov ax , 0x4F02 ; VESA SuperVGA BIOS - SET SuperVGA VIDEO MODE - http://www.ctyme.com/intr/rb-0275.htm
119+ int 0x10
120+ cmp ax , 0x004F ; Return value in AX should equal 0x004F if supported and successful
121+ jne halt
122+
123+
124+
125+
126+
127+ mov bl , 'B' ; 'B' as we booted via BIOS
128+
129+ ; At this point we are done with real mode and BIOS interrupts. Jump to 32-bit mode.
130+ cli ; No more interrupts
131+ lgdt [ cs :GDTR32 ] ; Load GDT register
132+ mov eax , cr0
133+ or al , 0x01 ; Set protected mode bit
134+ mov cr0 , eax
135+ ;;jmp 8:0x8000 ; Jump to 32-bit protected mode
136+
137+ ;;;;;;;;;;;;;; esto tiene que ser a start32
138+ ;;jmp 8:0x8000
139+ jmp 8 :start32
140+ ;;;;;;;;;;;;;;; here ends mbr completion
141+
142+
143+ ;;==============================================================================
144+ ;; failure | abort boot with error notification
145+ ;;==============================================================================
146+ ;; Argument:
147+ ;; -- si: string.
148+ ;;==============================================================================
149+
150+ failure:
151+ call print
152+ halt:
153+ ;;.halt:
154+ ;;mov si, msg_halt
155+ call print
156+ hlt
157+ jmp $
158+
159+
160+ ;;msg_halt: db "System halted", 0
161+
162+
163+ ;;==============================================================================
164+ ;; print | Imprime a pantalla usando bootservice.
165+ ;;==============================================================================
166+ ;; Argumentos:
167+ ;; -- si: string addr 16 bits.
168+ ;;==============================================================================
169+
170+
171+ ;; TO-DO: pasar a libreria, esta repetido del mbr
172+ print:
173+ pusha
174+ mov ah , 0x0e ;; int 0x10: write text in teletype mode.
175+
176+ .next:
177+ lodsb
178+ cmp al , 0
179+ je .fin
180+ int 0x10 ;; Write boot service.
181+ jmp .next
182+
183+ .fin:
184+ popa
185+ ret
186+
187+
188+
189+
190+ BITS 32
191+
192+
193+
194+ ;;;Pasaje 32 to 64 bits
195+ start32:
196+ mov [ p_BootDisk ], bh ;; Save disk from where system was booted from
197+
198+ mov eax , 16 ;; Set the correct segment registers
199+ mov ds , ax
200+ mov es , ax
201+ mov ss , ax
202+ mov fs , ax
203+ mov gs , ax
204+
205+ xor eax , eax ;; Clear all registers
206+ xor ebx , ebx
207+ xor ecx , ecx
208+ xor edx , edx
209+ xor esi , esi
210+ xor edi , edi
211+ xor ebp , ebp
212+ mov esp , 0x8000 ; Set a known free location for the stack
213+
214+
215+ ;;;;;;;;;;;;;;;; importante, aqui toma lo que le ha pasado desde bios, esto esta dentro de ifdef
216+ ;;;; por eso lo que le pasa difiere de uefi
217+ ;;;; leer info de video de VBEModeInfoBlock esta bien. Tener en cuenta que aqui es solo la asignacion para bios
218+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
219+
220+ ; Save the frame buffer address, size (after its calculated), and the screen x,y
221+ xor eax , eax
222+ xor ebx , ebx
223+
224+ mov ax , [ 0x5F00 + 16 ] ; BytesPerScanLine (modo vesa)
225+ push eax
226+
227+ mov bx , [ 0x5F00 + 16 + 2 * 2 ] ; YResolution (vesa)
228+ push ebx
229+
230+ mov ax , [ 0x5F00 + 16 + 2 ] ; XResolution (vesa)
231+ push eax
232+
233+ mul ebx
234+ mov ecx , eax
235+ shl ecx , 2 ; Quick multiply by 4
236+
237+
238+ ;; aqui en bios, deja las cosas en el mismo orden que uefi
239+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
240+ ;;;[0x00005F00] ; Frame buffer base
241+ ;;;[0x00005F08] ; Frame buffer size (bytes)
242+ ;;;[0x00005F10] ; Screen X
243+ ;;;;[0x00005F12] ; Screen Y
244+ ;;;;[0x00005F14] ; PixelsPerScanLine
245+ ;;;;; recontramega importante (para bios, no uefi), aqui va a colocar
246+
247+ mov edi , 0x5F00
248+ mov eax , [ 0x5F00 + 40 ] ;;;; ya que para bios, el vbeinfoblock tiene esta estructura (framebuffer en +40)
249+ stosd ; 64-bit Frame Buffer Base (low)
250+ ;;;;;;;; y pasandolo aqui 0x5f00 esta unificando un vbeInfoblock con estructura nueva tanto
251+ ;;;;;;;; para efi como para bios
252+
253+ xor eax , eax
254+ stosd ; 64-bit Frame Buffer Base (high) completa qword
255+
256+ mov eax , ecx
257+ stosd ; 64-bit Frame Buffer Size in bytes (low)
258+ xor eax , eax
259+ stosd ; 64-bit Frame Buffer Size in bytes (high)
260+
261+ pop eax
262+ stosw ; 16-bit Screen X
263+
264+ pop eax
265+ stosw ; 16-bit Screen Y
266+
267+ pop eax
268+ shr eax , 2 ; 4 bytes / px => bpsl/4
269+ stosw ; PixelsPerScanLine
270+ mov eax , 32
271+ stosw ; BitsPerPixel
272+
273+ ; Clear memory for the Page Descriptor Entries (0x10000 - 0x5FFFF)
274+ mov edi , 0x00210000
275+ mov ecx , 81920
276+ rep stosd ; Write 320KiB
277+
278+ ; Create the temporary Page Map Level 4 Entries (PML4E)
279+ ; PML4 is stored at 0x0000000000202000, create the first entry there
280+ ; A single PML4 entry can map 512GiB with 2MiB pages
281+ ; A single PML4 entry is 8 bytes in length
282+ cld
283+ mov edi , 0x00202000 ; Create a PML4 entry for the first 4GiB of RAM
284+ mov eax , 0x00203007 ; Bits 0 (P), 1 (R/W), 2 (U/S), location of low PDP (4KiB aligned)
285+ stosd
286+ xor eax , eax
287+ stosd
288+
289+ ; Create the temporary Page-Directory-Pointer-Table Entries (PDPTE)
290+ ; PDPTE is stored at 0x0000000000203000, create the first entry there
291+ ; A single PDPTE can map 1GiB with 2MiB pages
292+ ; A single PDPTE is 8 bytes in length
293+ ; 4 entries are created to map the first 4GiB of RAM
294+ mov ecx , 4 ; number of PDPE's to make.. each PDPE maps 1GiB of physical memory
295+ mov edi , 0x00203000 ; location of low PDPE
296+ mov eax , 0x00210007 ; Bits 0 (P), 1 (R/W), 2 (U/S), location of first low PD (4KiB aligned)
297+ pdpte_low_32:
298+ stosd
299+ push eax
300+ xor eax , eax
301+ stosd
302+ pop eax
303+ add eax , 0x00001000 ; 4KiB later (512 records x 8 bytes)
304+ dec ecx
305+ cmp ecx , 0
306+ jne pdpte_low_32
307+
308+ ; Create the temporary low Page-Directory Entries (PDE).
309+ ; A single PDE can map 2MiB of RAM
310+ ; A single PDE is 8 bytes in length
311+ mov edi , 0x00210000 ; Location of first PDE
312+ mov eax , 0x0000008F ; Bits 0 (P), 1 (R/W), 2 (U/S), 3 (PWT), and 7 (PS) set
313+ xor ecx , ecx
314+ pde_low_32: ; Create a 2 MiB page
315+ stosd
316+ push eax
317+ xor eax , eax
318+ stosd
319+ pop eax
320+ add eax , 0x00200000 ; Increment by 2MiB
321+ inc ecx
322+ cmp ecx , 2048
323+ jne pde_low_32 ; Create 2048 2 MiB page maps.
324+
325+ ; Load the GDT
326+ lgdt [ tmpGDTR64 ]
327+
328+ ; Enable extended properties
329+ mov eax , cr4
330+ or eax , 0x0000000B0 ; PGE (Bit 7), PAE (Bit 5), and PSE (Bit 4)
331+ mov cr4 , eax
332+
333+ ; Point cr3 at PML4
334+ mov eax , 0x00202008 ; Write-thru enabled (Bit 3)
335+ mov cr3 , eax
336+
337+ ; Enable long mode and SYSCALL/SYSRET
338+ mov ecx , 0xC0000080 ; EFER MSR number
339+ rdmsr ; Read EFER
340+ or eax , 0x00000101 ; LME (Bit 8)
341+ wrmsr ; Write EFER
342+
343+ mov bl , 'B'
344+ mov bh , byte [ p_BootDisk ]
345+
346+ ; Enable paging to activate long mode
347+ mov eax , cr0
348+ or eax , 0x80000000 ; PG (Bit 31)
349+ mov cr0 , eax
350+
351+ jmp SYS64_CODE_SEL:start64 ; Jump to 64-bit mode
0 commit comments