[coreboot] [USBOPTIONROM] Turn Real Mode to PM mode

Jason Wang wangqingpei at gmail.com
Thu May 21 19:11:14 CEST 2009


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.coreboot.org/pipermail/coreboot/attachments/20090522/5aad9113/attachment.html>


More information about the coreboot mailing list