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