# 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