Created
June 11, 2021 06:07
-
-
Save cpuwolf/201b51336d14dc5d637c4bb4837a9f93 to your computer and use it in GitHub Desktop.
IA real mode, protected mode, 64bit mode, 64bit compat mode
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# we can boot from BOOTLOADER function logic_boot_emmc_init() | |
# please make sure paging is disabled | |
# before enter into sbft_call | |
.text | |
.section REALMODE_CODE, "ax" | |
.code32 | |
########################################## | |
# | |
# Save original BOOTLOADER execution environment | |
# | |
########################################## | |
.globl sbft_call | |
sbft_call: | |
cld | |
push %fs | |
push %es | |
push %ds | |
push %eax | |
push %ebp | |
push %edi | |
push %esi | |
push %edx | |
push %ecx | |
push %ebx | |
# backup BOOTLOADER stack point | |
movl %esp, (psi_esp) | |
# fill up SBFT return address(64bit address) | |
movl $x64_mode, (0x1F08) | |
movl $0, (0x1F0C) | |
# ebp is IRAM data base | |
movl 44(%esp), %ebp | |
# esi:edi is set to SBFT RM entry address | |
movl 48(%esp), %esi | |
movl 52(%esp), %edi | |
movw %di, (sbft_addr) | |
movw %si, (sbft_addr+4) | |
# ready to switch to real mode | |
cli | |
# disable paging | |
movl %cr0, %eax | |
andl $(0x7FFFFFFF), %eax | |
movl %eax, %cr0 | |
# flush TLB | |
xorl %eax, %eax | |
movl %eax, %cr3 | |
# load real mode IDT | |
lidtl real_mode_idt | |
# load real mode GDT | |
lgdtl real_mode_gdt | |
# load segment | |
movw $0x10, %ax | |
movw %ax, %ds | |
movw %ax, %ss | |
movw %ax, %es | |
# jump 16bit protected mode | |
ljmpw $8, $real_mode | |
nop | |
############################################# | |
# | |
# Recovery original BOOTLOADER execution environment | |
# | |
############################################# | |
psi_recovery: | |
pop %ebx | |
pop %ecx | |
pop %edx | |
pop %esi | |
pop %edi | |
pop %ebp | |
pop %eax | |
pop %ds | |
pop %es | |
pop %fs | |
# fetch SBFT result | |
movl (0x1F04), %eax | |
ret | |
nop | |
########################################## | |
# | |
# 16 bit Real mode | |
# | |
########################################## | |
.code16 | |
.balign 16 | |
real_mode: | |
# switch to real mode | |
movl %cr0, %eax | |
andl $(0xFFFFFFFE), %eax | |
movl %eax, %cr0 | |
# far jump | |
.byte 0xEA | |
.word 5f, 0 | |
5: | |
# setup real mode segment | |
movw %cs, %ax | |
movw %ax, %ds | |
movw %ax, %es | |
movw %ax, %ss | |
# jump to SBFT entry | |
# ljmpw $0x0000, $0x2700 | |
ljmpw *(sbft_addr) | |
nop | |
########################################## | |
# | |
# switch 64 bit IA32-e mode | |
# to compatibility mode | |
# | |
########################################## | |
.code32 | |
.balign 16 | |
x64_mode: | |
nop | |
nop | |
# switch to 32-bit data segment | |
movl $0x8, %eax | |
movl %eax, %ds | |
movl $x64_gdt_table, %edi | |
lgdtl (%edi) | |
movl $0x10, %eax | |
movl %eax, %ds | |
movl %eax, %ss | |
movl %eax, %es | |
movl %eax, %fs | |
movl %eax, %gs | |
# 64 bit far jump simulation | |
# xorq %rax, %rax (needs 64bit compiler) | |
.byte 0x48 | |
xorl %eax, %eax | |
movl $0x10, %eax | |
pushl %eax | |
movl %esp, %eax | |
pushl %eax | |
pushf | |
movl $0x8, %eax | |
pushl %eax | |
movl $x64_compat, %eax | |
pushl %eax | |
# iretq (needs 64bit compiler) | |
.byte 0x48 | |
iretl | |
nop | |
########################################## | |
# | |
# compatibility mode | |
# | |
########################################## | |
x64_compat: | |
# NOW! we are in 64bit compatibility mode (32bit code) | |
# disable paging, will set IA32_EFER.LMA = 0 | |
movl %cr0, %eax | |
andl $0x7FFFFFFF, %eax | |
movl %eax, %cr0 | |
# flush TLB | |
xorl %eax, %eax | |
movl %eax, %cr3 | |
# set IA32_EFER.LMA = 0 | |
xorl %eax, %eax | |
xorl %edx, %edx | |
movl $0xC0000080, %ecx | |
wrmsr | |
########################################## | |
# | |
# 32 bit protected mode | |
# | |
########################################## | |
x32_prot: | |
# disable MTRR | |
# return EDX:EAX | |
movl $0x2FF, %ecx | |
rdmsr | |
andl $0xFFFFF7FF, %eax | |
wrmsr | |
# cache clean all | |
wbinvd | |
# recovery BOOTLOADER CPU mode | |
# setup GDT | |
call gdt_init | |
# setup IDT | |
call idt_init | |
# setup MTRR | |
call mmu_bootcore_mtrr_setup | |
# enable paging | |
call mmu_bootcore_paging_enable | |
# recovery BOOTLOADER | |
movl (psi_esp), %esp | |
jmp psi_recovery | |
nop | |
.balign 16 | |
sbft_addr: | |
.word 0 | |
.word 0 | |
.balign 16 | |
real_mode_idt: | |
.word 0xFFFF | |
.long 0 | |
.balign 16 | |
real_mode_gdt: | |
# GDT0 | |
.word 0xFFFF | |
.long real_mode_gdt | |
.word 0 | |
# GDT1 16bit code segment | |
.word 0xFFFF | |
.long 0x9B000000 + 0 | |
.word 0 | |
# GDT2 16bit data segment | |
.word 0xFFFF | |
.long 0x93000000 + 0 | |
.word 0 | |
.balign 16 | |
x64_gdt: | |
# GDT0 dummy 0x0 | |
.quad 0x0 | |
# GDT2 32bit code segment 0x8 | |
.quad 0x00CF9B000000FFFF | |
# GDT1 32bit data segment 0x10 | |
.quad 0x00CF93000000FFFF | |
x64_gdt_end: | |
.balign 16 | |
x64_gdt_table: | |
# 64 bit GDT | |
.short x64_gdt_end - x64_gdt - 1 | |
.long x64_gdt | |
.long 0 | |
psi_esp: .long 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment