[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] rombios: Simplify 32-bit gateway and avoid need for EBDA space.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1232641926 0
# Node ID b10fd9f4fe38c38069b140bf8689c5fc15cd595f
# Parent  d52921c18c3d0171bccb4651cca8412f2fff2dd9
rombios: Simplify 32-bit gateway and avoid need for EBDA space.

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 tools/firmware/rombios/32bitgateway.h |   18 -
 tools/firmware/rombios/32bitgateway.c |  458 ++++++++--------------------------
 tools/firmware/rombios/rombios.c      |    4 
 3 files changed, 120 insertions(+), 360 deletions(-)

diff -r d52921c18c3d -r b10fd9f4fe38 tools/firmware/rombios/32bitgateway.c
--- a/tools/firmware/rombios/32bitgateway.c     Thu Jan 22 11:21:43 2009 +0000
+++ b/tools/firmware/rombios/32bitgateway.c     Thu Jan 22 16:32:06 2009 +0000
@@ -19,8 +19,10 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
  * Copyright (C) IBM Corporation, 2006
+ * Copyright (c) 2008, Citrix Systems, Inc.
  *
  * Author: Stefan Berger <stefanb@xxxxxxxxxx>
+ * Author: Keir Fraser <keir.fraser@xxxxxxxxxx>
  */
 
 /*
@@ -34,384 +36,162 @@
  *  (4 bytes) even for uint16_t, so casting to 32bit from bcc is a good idea.
  */
 
-#define SEGMENT_OFFSET  0xf0000
-#define REAL_MODE_CODE_SEGMENT  0xf000
+/* At most 32 bytes in argument list to a 32-bit function. */
+#define MAX_ARG_BYTES 32
 
-#define START_PM_CODE  USE32
-#define END_PM_CODE    USE16
+#define REAL_MODE_CODE_OFFSET  0xf0000
 
-/* definition of used code/data segment descriptors */
-#define PM_NORMAL_CS (gdt_entry_pm_cs       - gdt_base)
+/* Definitions of code/data segment descriptors. */
+#define PM_32BIT_CS  (gdt_entry_pm_32bit_cs - gdt_base)
 #define PM_16BIT_CS  (gdt_entry_pm_16bit_cs - gdt_base)
 #define PM_32BIT_DS  (gdt_entry_pm_32bit_ds - gdt_base)
+#define PM_16BIT_DS  (gdt_entry_pm_16bit_ds - gdt_base)
 
-  ASM_START
+ASM_START
 
-    ; Switch into protected mode to allow access to 32 bit addresses.
-    ; This function allows switching into protected mode.
-    ; (the specs says big real mode, but that will not work)
+    .align 16
+gdt_base:
+    .word 0,0
+    .byte 0,0,0,0
+gdt_entry_pm_32bit_cs:
+    .word 0xffff, 0x0000
+    .byte 0x00, 0x9b, 0xcf, 0x00
+gdt_entry_pm_16bit_cs:
+    .word 0xffff, 0x0000
+    .byte REAL_MODE_CODE_OFFSET >> 16, 0x9b, 0x0, 0x0
+gdt_entry_pm_32bit_ds:
+    .word 0xffff, 0x0000
+    .byte 0x0, 0x93, 0xcf, 0x0
+gdt_entry_pm_16bit_ds:
+    .word 0xffff, 0x0000
+    .byte 0x0, 0x93, 0x0, 0x0
+gdt_entry_end:
+
+protmode_gdtdesc:
+    .word (gdt_entry_end - gdt_base) - 1
+    .long gdt_base | REAL_MODE_CODE_OFFSET
+
+realmode_gdtdesc:
+    .word 0xffff
+    .long 0x0
+
+Upcall:
+    ; Do an upcall into 32 bit space
     ;
-    ; preserves all registers and prepares cs, ds, es, ss for usage
-    ; in protected mode; while in prot.mode interrupts remain disabled
-switch_to_protmode:
+    ; Input:
+    ; bx: index of function to call
+    ; Ouput:
+    ; dx, ax: 32 bit result of call (even if 'void' is expected)
+
+    ; Save caller state, stack frame offsets listed below
+#define esp_off     0
+#define ss_off      4
+#define es_off      6
+#define ds_off      8
+#define flags_off   10
+#define retaddr_off 12
+#define args_off    14
+    pushf
     cli
+    push ds
+    push es
+    push ss
+    push esp
 
-    ; have to fix the stack for proper return address in 32 bit mode
-    push WORD #(REAL_MODE_CODE_SEGMENT>>12)    ;extended return address
-    push bp                                    ;pop@A1
-    mov bp, sp
-    push eax                                   ;pop@A2
-    mov eax, 2[bp]                             ; fix return address
-    rol eax, #16
-    mov 2[bp], eax
+    ; Find the 32-bit function address via a table lookup
+    push si
+    rol bx, #2
+    mov si, #jmptable
+    seg cs
+    mov eax, dword ptr [si+bx]
+    pop si
+    push eax
 
-    mov eax, esp
-    ror eax, #16                               ; hi(esp)
-
-    push bx                                    ; preserve before function call
-    push cx
-    push dx
-
-    push ax                                    ; prepare stack for
-    push es                                    ; call
-    push ds
-    push cs
-    push ss
-    call _store_segment_registers
-    add sp, #10                                        ; pop ax,es-ss
-
-    pop dx                                     ; restore after function call
-    pop cx
-    pop bx
-
-    ; calculate protected-mode esp from ss:sp
+    ; Calculate protected-mode esp from ss:sp
     and esp, #0xffff
     xor eax, eax
     mov ax, ss
-    rol eax, #4
-    add eax, esp
-    mov esp, eax
+    shl eax, #4
+    add esp, eax
 
+    ; Switch to protected mode
     seg cs
-    lgdt my_gdtdesc                            ; switch to own table
-
+    lgdt protmode_gdtdesc
     mov eax, cr0
-    or al, #0x1                                ; protected mode 'on'
+    or al, #0x1  ; protected mode on
     mov cr0, eax
-
-    jmpf DWORD (SEGMENT_OFFSET | switch_to_protmode_goon_1), #PM_NORMAL_CS
-
-    START_PM_CODE
-
-switch_to_protmode_goon_1:
-    mov ax, #PM_32BIT_DS                       ; 32 bit segment that allows
-    mov ds, ax                                 ; to reach all 32 bit
-    mov es, ax                                 ; addresses
+    jmpf DWORD (REAL_MODE_CODE_OFFSET|upcall1), #PM_32BIT_CS
+upcall1:
+    USE32
+    mov ax, #PM_32BIT_DS
+    mov ds, ax
+    mov es, ax
     mov ss, ax
 
-    pop eax                                    ;@A2
-    pop bp                                     ;@A1
-    ret
+    ; Marshal arguments and call 32-bit function
+    pop eax
+    mov ecx, #MAX_ARG_BYTES/4
+upcall2:
+    push MAX_ARG_BYTES-4+args_off[esp]
+    loop upcall2
+    call eax
+    add esp, #MAX_ARG_BYTES
+    mov ecx, eax  ; Result in ecx
 
-    END_PM_CODE
+    ; Restore real-mode stack pointer
+    xor eax, eax
+    mov ax, ss_off[esp]
+    shl eax, 4
+    sub esp, eax
+    mov bx, ax    ; Real-mode ss in bx
 
-
-
-    .align 16
-gdt_base:
-    ; see Intel SW Dev. Manuals section 3.4.5, Volume 3 for meaning of bits
-    .word 0,0
-    .byte 0,0,0,0
-
-gdt_entry_pm_cs:
-    ; 32 bit code segment for protected mode
-    .word 0xffff, 0x0000
-    .byte 0x00, 0x9b, 0xcf, 0x00
-
-gdt_entry_pm_16bit_cs:
-    ; temp. 16 bit code segment used while in protected mode
-    .word 0xffff, 0x0000
-    .byte SEGMENT_OFFSET >> 16, 0x9b, 0x0, 0x0
-
-gdt_entry_pm_32bit_ds:
-    ; (32 bit) data segment (r/w) reaching all possible areas in 32bit memory
-    ; 4kb granularity
-    .word 0xffff, 0x0000
-    .byte 0x0, 0x93, 0xcf, 0x0
-gdt_entry_end:
-
-my_gdtdesc:
-    .word (gdt_entry_end - gdt_base) - 1
-    .long gdt_base | SEGMENT_OFFSET
-
-
-realmode_gdtdesc:                              ;to be used in real mode
-    .word 0xffff
-    .long 0x0
-
-
-
-switch_to_realmode:
-    ; Implementation of switching from protected mode to real mode
-    ; prepares cs, es, ds, ss to be used in real mode
-    ; spills   eax
-    START_PM_CODE
-
-    ; need to fix up the stack to return in 16 bit mode
-    ; currently the 32 bit return address is on the stack
-    pop eax
-    push ax
-
-    push bx                                    ;pop@1
-    push si                                    ;pop@2
-
-    call _ebda_ss_offset32                     ; get the offset of the ss
-    mov bx, ax                                 ; entry within the ebda.
-
-    jmpf switch_to_realmode_goon_1, #PM_16BIT_CS
-
-    END_PM_CODE
-
-switch_to_realmode_goon_1:
+    ; Return to real mode
+    jmpf upcall3, #PM_16BIT_CS
+upcall3:
+    USE16
+    mov ax, #PM_16BIT_DS
+    mov ds, ax
+    mov es, ax
+    mov ss, ax
     mov eax, cr0
-    and al, #0xfe                              ; protected mode 'off'
+    and al, #0xfe ; protected mode off
     mov cr0, eax
-
-    jmpf switch_to_realmode_goon_2, #REAL_MODE_CODE_SEGMENT
-
-switch_to_realmode_goon_2:
-
-    ; get orig. 'ss' without using the stack (no 'call'!)
-    xor eax, eax                       ; clear upper 16 bits (and lower)
-    mov ax, #0x40                      ; where is the ebda located?
-    mov ds, ax
-    mov si, #0xe
-    seg ds
-    mov ax, [si]                       ; ax = segment of ebda
-
-    mov ds, ax                         ; segment of ebda
-    seg ds
-    mov ax, [bx]                       ; stack segment - bx has been set above
-    mov ss, ax
-
-    ; from esp and ss calculate real-mode sp
-    rol eax, #4
-    sub esp, eax
-
-    push dx                            ;preserve before call(s)
-    push cx
-    push bx
-
-    call _get_register_ds              ; get orig. 'ds'
-    mov ds, ax
-    call _get_register_es              ; get orig. 'es'
-    mov es, ax
-    call _get_register_esp_hi          ; fix the upper 16 bits of esp
-    ror esp, #16
-    mov sp, ax
-    rol esp, #16
-
-    pop bx
-    pop cx
-    pop dx
-
+    jmpf upcall4, #REAL_MODE_CODE_OFFSET>>4
+upcall4:
     seg cs
     lgdt realmode_gdtdesc
 
-    sti                                                ; allow interrupts
+    ; Restore real-mode ss
+    mov ss, bx
 
-    pop si                                     ;@2
-    pop bx                                     ;@1
+    ; Convert result into dx:ax format
+    mov eax, ecx
+    ror eax, #16
+    mov dx, ax
+    ror eax, #16
 
+    ; Restore caller state and return
+    pop esp
+    pop bx ; skip ss
+    pop es
+    pop ds
+    popf
     ret
-
-    ASM_END
-
-/*
- * Helper function to get the offset of the reg_ss within the ebda struct
- * Only 'C' can tell the offset.
- */
-Bit16u
-ebda_ss_offset32()
-{
-    ASM_START
-    START_PM_CODE                              // need to have this
-    ASM_END                                    // compiled for protected mode
-    return &EbdaData->upcall.reg_ss;           // 'C' knows the offset!
-    ASM_START
-    END_PM_CODE
-    ASM_END
-}
-
-/*
- * Two often-used functions
- */
-Bit16u
-read_word_from_ebda(offset)
-    Bit16u offset;
-{
-       Bit16u ebda_seg = read_word(0x0040, 0x000E);
-       return read_word(ebda_seg, offset);
-}
-
-Bit32u
-read_dword_from_ebda(offset)
-    Bit16u offset;
-{
-       Bit16u ebda_seg = read_word(0x0040, 0x000E);
-       return read_dword(ebda_seg, offset);
-}
-
-/*
- * Store registers in the EBDA; used to keep the registers'
- * content in a well-defined place during protected mode execution
- */
-  void
-store_segment_registers(ss, cs, ds, es, esp_hi)
-  Bit16u ss, cs, ds, es, esp_hi;
-{
-       Bit16u ebda_seg = read_word(0x0040, 0x000E);
-       write_word(ebda_seg, &EbdaData->upcall.reg_ss, ss);
-       write_word(ebda_seg, &EbdaData->upcall.reg_cs, cs);
-       write_word(ebda_seg, &EbdaData->upcall.reg_ds, ds);
-       write_word(ebda_seg, &EbdaData->upcall.reg_es, es);
-       write_word(ebda_seg, &EbdaData->upcall.esp_hi, esp_hi);
-}
-
-
-  void
-store_returnaddress(retaddr)
-   Bit16u retaddr;
-{
-       Bit16u ebda_seg = read_word(0x0040, 0x000E);
-       write_word(ebda_seg, &EbdaData->upcall.retaddr, retaddr);
-}
-
-Bit16u
-get_returnaddress()
-{
-       return read_word_from_ebda(&EbdaData->upcall.retaddr);
-}
-
-/*
- * get the segment register 'cs' value from the EBDA
- */
-Bit16u
-get_register_cs()
-{
-       return read_word_from_ebda(&EbdaData->upcall.reg_cs);
-}
-
-/*
- * get the segment register 'ds' value from the EBDA
- */
-Bit16u
-get_register_ds()
-{
-       return read_word_from_ebda(&EbdaData->upcall.reg_ds);
-}
-
-/*
- * get the segment register 'es' value from the EBDA
- */
-Bit16u
-get_register_es()
-{
-       return read_word_from_ebda(&EbdaData->upcall.reg_es);
-}
-
-/*
- * get the upper 16 bits of the esp from the EBDA
- */
-Bit16u
-get_register_esp_hi()
-{
-       return read_word_from_ebda(&EbdaData->upcall.esp_hi);
-}
-
-
-
-/********************************************************/
-
-
-ASM_START
-
-Upcall:
-       ; do the upcall into 32 bit space
-       ; clear the stack frame so that 32 bit space sees all the parameters
-       ; on the stack as if they were prepared for it
-       ; ---> take the 16 bit return address off the stack and remember it
-       ;
-       ; Input:
-       ; bx: index of function to call
-       ; Ouput:
-       ; dx, ax: 32 bit result of call (even if 'void' is expected)
-
-       push bp                         ;pop @1
-       mov bp, sp
-       push si                         ;pop @2
-
-       mov ax, 2[bp]                   ; 16 bit return address
-       push ax
-       call _store_returnaddress       ; store away
-       pop ax
-
-       rol bx, #2
-       mov si, #jmptable
-       seg cs
-       mov eax, dword ptr [si+bx]      ; address to call from table
-
-       pop si                          ;@2
-       pop bp                          ;@1
-
-       add sp, #2                      ; remove 16bit return address from stack
-
-       call switch_to_protmode
-       START_PM_CODE
-
-       call eax                        ; call 32bit function
-       push eax                        ; preserve result
-
-       call switch_to_realmode         ; back to realmode
-       END_PM_CODE
-
-       pop eax                         ; get result
-
-       push word 0x0000                ; placeholder for 16 bit return address
-       push bp
-       mov bp,sp
-       push eax                        ; preserve work register
-
-       call _get_returnaddress
-       mov 2[bp], ax                   ; 16bit return address onto stack
-
-       pop eax
-       pop bp
-
-       ror eax, #16                    ; result into dx/ax
-       mov dx, ax                      ; hi(res) -> dx
-       ror eax, #16
-
-       ret
-
 
 /* macro for functions to declare their call into 32bit space */
 MACRO DoUpcall
-       mov bx, #?1
-       jmp Upcall
+    mov bx, #?1
+    jmp Upcall
 MEND
-
 
 ASM_END
 
 #include "32bitprotos.h"
-#include "32bitgateway.h"
-
 #include "tcgbios.c"
 
 Bit32u get_s3_waking_vector()
 {
-       ASM_START
-       DoUpcall(IDX_GET_S3_WAKING_VECTOR)
-       ASM_END
+    ASM_START
+    DoUpcall(IDX_GET_S3_WAKING_VECTOR)
+    ASM_END
 }
diff -r d52921c18c3d -r b10fd9f4fe38 tools/firmware/rombios/32bitgateway.h
--- a/tools/firmware/rombios/32bitgateway.h     Thu Jan 22 11:21:43 2009 +0000
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-#ifndef GATEWAY
-#define GATEWAY
-
-#include "32bitprotos.h"
-
-void test_gateway();
-
-/* extension for the EBDA */
-typedef struct {
-  Bit16u reg_ss;
-  Bit16u reg_cs;
-  Bit16u reg_ds;
-  Bit16u reg_es;
-  Bit16u esp_hi;
-  Bit16u retaddr;
-} upcall_t;
-
-#endif
diff -r d52921c18c3d -r b10fd9f4fe38 tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c  Thu Jan 22 11:21:43 2009 +0000
+++ b/tools/firmware/rombios/rombios.c  Thu Jan 22 16:32:06 2009 +0000
@@ -726,7 +726,7 @@ typedef struct {
     } cdemu_t;
 #endif // BX_ELTORITO_BOOT
 
-#include "32bitgateway.h"
+#include "32bitprotos.h"
 
   // for access to EBDA area
   //     The EBDA structure should conform to
@@ -752,8 +752,6 @@ typedef struct {
     // El Torito Emulation data
     cdemu_t cdemu;
 #endif // BX_ELTORITO_BOOT
-
-    upcall_t upcall;
     } ebda_data_t;
 
   #define EBDA_CMOS_SHUTDOWN_STATUS_OFFSET 1

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.