Hi all,
I am trying to make optionrom can be run in PM 32 bit mode, and my work
flow is 1)load gdt 2)open A20 3) set cro bit 4) take the long jump to 32
bit PM. After step 3) optionrom has already in 16bit PM,but the long jump
did not work, which should run in to 32bit PM. I paste the whole assemble
file here. Is there any one who can give a hand about this?
.text
.code16 # Real mode by default (prefix 66 or 67 to 32 bits instructions)
rom_size = 0x04 # ROM size in multiple of 512 bytes
os_load_seg = 0x0000 # this is working if lgdt is passed with an
absolute address
os_code_size = ((rom_size - 1)*512)
os_code_size16 = ( os_code_size / 2 )
_base_address:
.word 0xAA55 # Rom signature
.byte rom_size # Size of this ROM, see definition above
jmp _init # jump to PCI initialization function
.org 0x18
.word _pci_data_struct # Pointer to PCI HDR structure (at 18h)
.word _pnp_header # PnP Expansion Header Pointer (at 1Ah)
# --------------------------------------------
# PCI data structure
#
_pci_data_struct:
.ascii "PCIR" # PCI Header Sign
.word 0x8086 # Vendor ID
.word 0x7000 # Device ID
.word 0x00 # VPD
.word 0x18 # PCI data struc length (byte)
.byte 0x00 # PCI Data struct Rev
.byte 0x02 # Base class code, 02h == Network Controller
.byte 0x00 # Sub class code = 00h and interface = 00h -->Ethernet
Controller
.byte 0x00 # Interface code, see PCI Rev2.1 Spec Appendix D
.word rom_size # Image length in mul of 512 byte, little endian format
.word 0x00 # rev level
.byte 0x00 # Code type = x86
.byte 0x80 # last image indicator
.word 0x00 # reserved
# -----------------------------
# PnP ROM Bios Header
#
_pnp_header:
.ascii "$PnP" # PnP Rom header sign
.byte 0x01 # Structure Revision
.byte 0x02 # Header structure Length in mul of 16 bytes
.word 0x00 # Offset to next header (00 if none)
.byte 0x00 # reserved
.byte 0x00 # 8-Bit checksum for this header, calculated and
patched by build_rom
.long 0x00 # PnP Device ID (0h in Realtek RPL ROM, we just
follow it)
.word 0x00 # pointer to manufacturer string, we use empty
string
.word 0x00 # pointer to product string, we use empty string
.byte 0x02,0x00,0x00 # Device Type code 3 byte
.byte 0x14 # Device Indicator, 14h from Realtek RPL ROM-->See
Page 18 of
# PnP BIOS spec., Lo nibble (4) means IPL device
.word 0x00 # Boot Connection Vector, 00h = disabled
.word 0x00 # Disconnect Vector, 00h = disabled
.word _start # Bootstrap Entry Vector (BEV)
.word 0x00 # reserved
.word 0x00 # Static resource Information vector (0000h if unused)
#--------------------------------------------------------------------
# PCI Option ROM initialization Code (init function)
#
_init:
///////////////////////////////////////////////
1: jmp 1b
jmp _setup
ret
////////////////////////////////////////////////////////
andw $0xCF, %ax # inform system BIOS that an IPL device attached
orw $0x20, %ax # see PnP spec 1.0A p21 for info's
lret # return far to system BIOS
#--------------------------------------------------------------------
# entry point/BEV implementation (invoked during bootstrap / int 19h)
#
.global _start # entry point
_start:
movw $0x9000, %ax # setup temporary stack
movw %ax, %ss # ss = 0x9000
# move ourself from "ROM" -> RAM 0x0000
movw %cs, %ax # initialize source address
movw %ax, %ds
movw $os_load_seg, %ax # point to OS segment
movw %ax, %es
movl $os_code_size16, %ecx
subw %di, %di
subw %si, %si
cld
rep
movsw
ljmp $os_load_seg, $_setup
_setup:
movw %cs, %ax # initialize segment registers (this is needed since lgdt
is %ds dependent??)
movw %ax, %ds
xorl %eax,%eax # Compute gdt_base
movw %cs,%ax # (Convert %ds:gdt to a linear ptr)
shll $4, %eax
addl $(gdt_desc), %eax
movl %eax, (gdt_desc+2)
lgdt (gdt_desc) # load GDT to GDTR (we load both limit and base address)
# ---------------------------------------------------------------------
# Switch to P-Mode and jump to C-Compiled kernel
#
cli # disable interrupt
// enable a20
inb $0x0092, %al
orb $0x02, %al
outb %al, $0x0092
movl %cr0, %eax # switch to P-Mode
or $1, %eax
movl %eax, %cr0 # haven't yet in P-Mode, we need a FAR Jump
.byte 0x66, 0xea # prefix + jmpi-opcode (this force P-Mode to be reached
i.e. CS updated)
.long do_pm # 32-bit linear address (jump target)
.word SEG_CODE_SEL # code segment selector
.code32
do_pm:
// xorl %esi, %esi
// xorl %edi, %edi
movw $0x10, %ax # Save data segment identifier (see GDT)
movw %ax, %ds
movw $0x18, %ax # Save stack segment identifier
movw %ax, %ss
movl $0x90000, %esp
jmp main # jump to main function
.align 8, 0 # align GDT in 8 bytes boundary
# -----------------------------------------------------
# GDT definition
#
gdt_marker: # dummy Segment Descriptor (GDT)
.long 0
.long 0
SEG_CODE_SEL = ( . - gdt_marker)
SegDesc1: # kernel CS (08h) PL0, 08h is an identifier
.word 0xffff # seg_length0_15
.word 0 # base_addr0_15
.byte 0 # base_addr16_23
.byte 0x9A # flags 9b?
.byte 0xcf # access
.byte 0 # base_addr24_31
SEG_DATA_SEL = ( . - gdt_marker)
SegDesc2: # kernel DS (10h) PL0
.word 0xffff # seg_length0_15
.word 0 # base_addr0_15
.byte 0 # base_addr16_23
.byte 0x92 # flags
.byte 0xcf # access
.byte 0 # base_addr24_31
SEG_STACK_SEL = ( . - gdt_marker)
SegDesc3: # kernel SS (18h) PL0
.word 0xffff # seg_length0_15
.word 0 # base_addr0_15
.byte 0 # base_addr16_23
.byte 0x92 # flags
.byte 0xcf # access
.byte 0 # base_addr24_31
gdt_end:
gdt_desc: .word (gdt_end - gdt_marker - 1) # GDT limit
.long (gdt_marker - _base_address-8) # physical addr of GDT
--
Jason Wang
Peking University