Index: root/xen-unstable.hg/tools/firmware/hvmloader/32bitbios_support.c =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/firmware/hvmloader/32bitbios_support.c @@ -0,0 +1,169 @@ +/* + * 32bitbios_support.c - relocation of 32bit BIOS implementation + * + * Stefan Berger, stefanb@xxxxxxxxxx + * Copyright (c) 2006, International Business Machines Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + */ +#include +#include +#include "util.h" +#include "config.h" + +#include "../rombios/32bit/32bitbios_flat.h" +#include "../rombios/32bit/jumptable.h" + + +/* + * relocate ELF file of type ET_REL + */ +static int relocate_elf(unsigned char *elfarray) { + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray; + Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff]; + int i; + + if (ehdr->e_type != ET_REL) { + printf("Not a relocatabel BIOS object file. Has type %d, need %d\n", + ehdr->e_type, ET_REL); + return -1; + } + + for (i = 0; i < ehdr->e_shnum; i++) { + if (!(shdr[i]).sh_flags & SHF_ALLOC) { + shdr[i].sh_addr = 0; + continue; + } + shdr[i].sh_addr = (Elf32_Addr)&elfarray[shdr[i].sh_offset]; + } + + for (i = 0; i < ehdr->e_shnum; i++) { + if (shdr[i].sh_type == SHT_REL && shdr[i].sh_addr != 0) { + Elf32_Shdr *targetsec = (Elf32_Shdr *)&(shdr[shdr[i].sh_info]); + Elf32_Shdr *symtabsec = (Elf32_Shdr *)&(shdr[shdr[i].sh_link]); + Elf32_Sym *syms = (Elf32_Sym *)symtabsec->sh_addr; + Elf32_Rel *rels = (Elf32_Rel *)shdr[i].sh_addr; + unsigned char *code = (unsigned char *)targetsec->sh_addr; + int j; + + for (j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++) { + int idx = ELF32_R_SYM(rels[j].r_info); + Elf32_Sym *symbol = &syms[idx]; + uint32_t *loc = (uint32_t *)&code[rels[j].r_offset]; + uint32_t fix = shdr[symbol->st_shndx].sh_addr + + symbol->st_value; + + switch (ELF32_R_TYPE(rels[j].r_info)) { + case R_386_PC32: + *loc += (fix - (uint32_t)loc); + break; + + case R_386_32: + *loc += fix; + break; + } + } + } else if (shdr[i].sh_type == SHT_RELA) { + return -2; + } + } + return 0; +} + +/* scan the rombios for the destination of the jumptable */ +static char* get_jump_table_start(void) +{ + char *bios_mem; + + for ( bios_mem = (char *)ROMBIOS_BEGIN; + bios_mem != (char *)ROMBIOS_END; + bios_mem++ ) { + if (strncmp(bios_mem, "___JMPT", 7) == 0) + return bios_mem; + } + + return NULL; +} + +/* copy relocated jumptable into the rombios */ +static int copy_jumptable(unsigned char *elfarray) +{ + int rc = 0; + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray; + Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff]; + Elf32_Shdr *shdr_strings = (Elf32_Shdr *)&shdr[ehdr->e_shstrndx]; + char *secstrings = (char *)&elfarray[shdr_strings->sh_offset]; + uint32_t *rombiosjumptable = (uint32_t *)get_jump_table_start(); + uint32_t *biosjumptable = NULL; + int i; + + if (rombiosjumptable == NULL) { + return -3; + } + + /* find the section with the jump table and copy to lower BIOS memory */ + for (i = 0; i < ehdr->e_shnum; i++) { + if (!strcmp(JUMPTABLE_SECTION_NAME, secstrings + shdr[i].sh_name)) { + uint32_t biosjumptableentries; + biosjumptable = (uint32_t *)shdr[i].sh_addr; + biosjumptableentries = shdr[i].sh_size / 4; + for (int j = 0; j < biosjumptableentries; j++) { + rombiosjumptable[j] = biosjumptable[j]; + if (biosjumptable[j] == 0 && + j < (biosjumptableentries - 1)) { + printf("WARNING: jumptable entry %d is NULL!\n",j); + } + } + break; + } + } + + if (biosjumptable == NULL) { + printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n"); + rc = -4; + } + + return 0; +} + +static int relocate_32bitbios(unsigned char *elfarray, uint32_t elfarraysize) +{ + int rc = 0; + uint32_t mask = (64 * 1024) - 1; + uint32_t to_malloc = (elfarraysize + mask) & ~mask; /* round to 64kb */ + unsigned char *highbiosarea; + + highbiosarea = (unsigned char *)(long) + e820_malloc((uint64_t)to_malloc, + E820_RESERVED, + (uint64_t)0xffffffff); + + if (highbiosarea != 0) { + memcpy(highbiosarea, elfarray, elfarraysize); + rc = relocate_elf(highbiosarea); + if (rc == 0) { + rc = copy_jumptable(highbiosarea); + } + } else { + rc = -5; + } + + return rc; +} + +int highbios_setup(void) +{ + return relocate_32bitbios((unsigned char *)highbios_array, + sizeof(highbios_array)); +} Index: root/xen-unstable.hg/tools/firmware/hvmloader/Makefile =================================================================== --- root.orig/xen-unstable.hg/tools/firmware/hvmloader/Makefile +++ root/xen-unstable.hg/tools/firmware/hvmloader/Makefile @@ -35,7 +35,7 @@ OBJCOPY = objcopy CFLAGS += -fno-builtin -O2 -msoft-float LDFLAGS = -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR) -SRCS = hvmloader.c mp_tables.c util.c smbios.c +SRCS = hvmloader.c mp_tables.c util.c smbios.c 32bitbios_support.c OBJS = $(patsubst %.c,%.o,$(SRCS)) .PHONY: all Index: root/xen-unstable.hg/tools/firmware/hvmloader/hvmloader.c =================================================================== --- root.orig/xen-unstable.hg/tools/firmware/hvmloader/hvmloader.c +++ root/xen-unstable.hg/tools/firmware/hvmloader/hvmloader.c @@ -314,6 +314,7 @@ int main(void) printf("Loading ROMBIOS ...\n"); memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios)); + highbios_setup(); apic_setup(); pci_setup(); Index: root/xen-unstable.hg/tools/firmware/hvmloader/util.h =================================================================== --- root.orig/xen-unstable.hg/tools/firmware/hvmloader/util.h +++ root/xen-unstable.hg/tools/firmware/hvmloader/util.h @@ -53,6 +53,7 @@ int get_apic_mode(void); /* String and memory functions */ int strcmp(const char *cs, const char *ct); +int strncmp(const char *s1, const char *s2, uint32_t n); char *strcpy(char *dest, const char *src); char *strncpy(char *dest, const char *src, unsigned n); unsigned strlen(const char *s); @@ -77,6 +78,10 @@ int vprintf(const char *fmt, va_list ap) /* Allocate region of specified type in the e820 table. */ uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask); +/* Prepare the 32bit BIOS */ +int highbios_setup(void); + + #define isdigit(c) ((c) >= '0' && (c) <= '9') #endif /* __HVMLOADER_UTIL_H__ */ Index: root/xen-unstable.hg/tools/firmware/Makefile =================================================================== --- root.orig/xen-unstable.hg/tools/firmware/Makefile +++ root/xen-unstable.hg/tools/firmware/Makefile @@ -7,7 +7,7 @@ TARGET := hvmloader/hvmloader INST_DIR := $(DESTDIR)/usr/lib/xen/boot SUBDIRS := -SUBDIRS += rombios +SUBDIRS += rombios rombios/32bit SUBDIRS += vgabios SUBDIRS += vmxassist SUBDIRS += hvmloader Index: root/xen-unstable.hg/tools/firmware/rombios/32bit/Makefile =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/firmware/rombios/32bit/Makefile @@ -0,0 +1,26 @@ +TARGET = 32bitbios_flat.h + +CFLAGS = -Wall -Werror -Wunused -Werror-implicit-function-declaration +CFLAGS += -fomit-frame-pointer -fno-builtin +CFLAGS += -I../ + +MODULES = 32bitbios.o + +.PHONY: all + +all : $(TARGET) + +clean :: + rm -rf *.o $(TARGET) + +$(TARGET) : 32bitbios_all.o $(SOURCES) + unref=`nm -u 32bitbios_all.o` + if [ "$$unref" != "" ]; then \ + echo "There are unresolved symbols in the BIOS."; \ + echo $$unref ; \ + else \ + bash mkhex highbios_array 32bitbios_all.o > $(TARGET); \ + fi + +32bitbios_all.o : 32bitbios.o $(MODULES) + ld -r $(MODULES) -o 32bitbios_all.o Index: root/xen-unstable.hg/tools/firmware/rombios/32bit/mkhex =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/firmware/rombios/32bit/mkhex @@ -0,0 +1,26 @@ +#!/bin/sh + +# +# mkhex: Generate C embeddable hexdumps +# +# Leendert van Doorn, leendert@xxxxxxxxxxxxxx +# Copyright (c) 2005, International Business Machines Corporation. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 59 Temple +# Place - Suite 330, Boston, MA 02111-1307 USA. +# + +echo "unsigned $1[] = {" +od -v -t x $2 | sed 's/^[0-9]* /0x/' | sed 's/ /, 0x/g' | sed 's/$/,/' +echo "};" + Index: root/xen-unstable.hg/tools/firmware/rombios/32bit/32bitbios.c =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/firmware/rombios/32bit/32bitbios.c @@ -0,0 +1,60 @@ +/* + * 32bitbios - jumptable for those function reachable from 16bit area + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Copyright (C) IBM Corporation, 2006 + * + * Author: Stefan Berger + */ +#include "rombios_compat.h" +#include "jumptable.h" +#include "32bitprotos.h" + +/* same prototypes as in the 16bit BIOS */ +Bit32u multiply(Bit32u a, Bit32u b) +{ + return a*b; +} + +Bit32u add(Bit32u a, Bit32u b) +{ + return a+b; +} + +static Bit32u stat_a = 0x1; +Bit32u set_static(Bit32u a) +{ + Bit32u _a = stat_a; + stat_a = a; + return _a; +} + + +/* + the jumptable that will be copied into the rombios in the 0xf000 segment + for every function that is to be called from the lower BIOS, make an entry + here. + */ +#define TABLE_ENTRY(idx, func) [idx] = (uint32_t)func +uint32_t jumptable[IDX_LAST+1] __attribute__((section (JUMPTABLE_SECTION_NAME))) = +{ + TABLE_ENTRY(IDX_MULTIPLY , multiply), + TABLE_ENTRY(IDX_ADD , add), + TABLE_ENTRY(IDX_SET_STATIC , set_static), + + + TABLE_ENTRY(IDX_LAST , 0) /* keep last */ +}; Index: root/xen-unstable.hg/tools/firmware/rombios/rombios.c =================================================================== --- root.orig/xen-unstable.hg/tools/firmware/rombios/rombios.c +++ root/xen-unstable.hg/tools/firmware/rombios/rombios.c @@ -724,6 +724,8 @@ typedef struct { } cdemu_t; #endif // BX_ELTORITO_BOOT +#include "32bitgateway.h" + // for access to EBDA area // The EBDA structure should conform to // http://www.cybertrails.com/~fys/rombios.htm document @@ -745,6 +747,7 @@ typedef struct { cdemu_t cdemu; #endif // BX_ELTORITO_BOOT + upcall_t upcall; } ebda_data_t; #define EbdaData ((ebda_data_t *) 0) @@ -1845,6 +1848,7 @@ print_bios_banner() printf(BX_APPNAME" BIOS, %d cpu%s, ", BX_SMP_PROCESSORS, BX_SMP_PROCESSORS>1?"s":""); printf("%s %s\n", bios_cvs_version_string, bios_date_string); printf("\n"); + test_gateway(); } //-------------------------------------------------------------------------- @@ -8766,6 +8770,10 @@ use16 386 #endif +ASM_END +#include "32bitgateway.c" +ASM_START + ;-------------------- #if BX_PCIBIOS use32 386 @@ -10553,13 +10561,23 @@ static Bit8u vgafont8[128*8]= }; #ifdef HVMASSIST +ASM_START + +// space for addresses in 32bit BIOS area; currently 256/4 entries +// are allocated +.org 0xcb00 +jmptable: +db 0x5F, 0x5F, 0x5F, 0x4A, 0x4D, 0x50, 0x54 ;; ___JMPT +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 64 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 128 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 192 bytes + // // MP Tables // just carve out some blank space for HVMLOADER to write the MP tables to // // NOTE: There should be enough space for a 32 processor entry MP table // -ASM_START .org 0xcc00 db 0x5F, 0x5F, 0x5F, 0x48, 0x56, 0x4D, 0x4D, 0x50 ;; ___HVMMP dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 64 bytes Index: root/xen-unstable.hg/tools/firmware/rombios/32bit/rombios_compat.h =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/firmware/rombios/32bit/rombios_compat.h @@ -0,0 +1,92 @@ +#ifndef ROMBIOS_COMPAT +#define ROMBIOS_COMPAT + +/* + * Compatibility functions and structures for transitioning between + * 16 bit Bochs BIOS and 32 bit BIOS code. + */ +#include + +#define ADDR_FROM_SEG_OFF(seg, off) (void *)((((uint32_t)(seg)) << 4) + (off)) + +typedef uint8_t Bit8u; +typedef uint16_t Bit16u; +typedef uint32_t Bit32u; + +#define SetCF(x) (x)->u.r8.flagsl |= 0x01 +#define SetZF(x) (x)->u.r8.flagsl |= 0x40 +#define ClearCF(x) (x)->u.r8.flagsl &= 0xfe +#define ClearZF(x) (x)->u.r8.flagsl &= 0xbf +#define GetCF(x) ((x)->u.r8.flagsl & 0x01) + +#define SET_CF() *FLAGS |= 0x0001 +#define CLEAR_CF() *FLAGS &= 0xfffe +#define GET_CF() (*FLAGS & 0x0001) + +#define SET_ZF() *FLAGS |= 0x0040 +#define CLEAR_ZF() *FLAGS &= 0xffbf + + +typedef struct { + union { + struct { + Bit32u edi, esi, ebp, esp; + Bit32u ebx, edx, ecx, eax; + } r32; + struct { + Bit16u di, filler1, si, filler2, bp, filler3, sp, filler4; + Bit16u bx, filler5, dx, filler6, cx, filler7, ax, filler8; + } r16; + struct { + Bit32u filler[4]; + Bit8u bl, bh; + Bit16u filler1; + Bit8u dl, dh; + Bit16u filler2; + Bit8u cl, ch; + Bit16u filler3; + Bit8u al, ah; + Bit16u filler4; + } r8; + } u; +} __attribute__((packed)) pushad_regs_t; + + + +static inline Bit32u read_dword(Bit16u seg, Bit16u off) +{ + uint32_t *addr = (uint32_t *)ADDR_FROM_SEG_OFF(seg,off); + return *addr; +} + +static inline Bit16u read_word(Bit16u seg, Bit16u off) +{ + uint16_t *addr = (uint16_t *)ADDR_FROM_SEG_OFF(seg,off); + return *addr; +} + +static inline Bit8u read_byte(Bit16u seg, Bit16u off) +{ + uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,off); + return *addr; +} + +static inline void write_dword(Bit16u seg, Bit16u off, Bit32u val) +{ + uint32_t *addr = (uint32_t *)ADDR_FROM_SEG_OFF(seg,off); + *addr = val; +} + +static inline void write_word(Bit16u seg, Bit16u off, Bit16u val) +{ + uint16_t *addr = (uint16_t *)ADDR_FROM_SEG_OFF(seg,off); + *addr = val; +} + +static inline void write_byte(Bit16u seg, Bit16u off, Bit8u val) +{ + uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,off); + *addr = val; +} + +#endif Index: root/xen-unstable.hg/tools/firmware/rombios/32bitprotos.h =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/firmware/rombios/32bitprotos.h @@ -0,0 +1,22 @@ +#ifndef PROTOS_HIGHBIOS +#define PROTOS_HIGHBIOS + +/* bcc does not like 'enum' */ +#define IDX_MULTIPLY 0 +#define IDX_ADD 1 +#define IDX_SET_STATIC 2 +#define IDX_LAST 3 /* keep last! */ + + +#ifdef GCC_PROTOS + #define PARMS(x...) x +#else + /* bcc doesn't want any parameter types in prototypes */ + #define PARMS(x...) +#endif + +Bit32u multiply( PARMS(Bit32u a, Bit32u b) ); +Bit32u add( PARMS(Bit32u a, Bit32u b) ); +Bit32u set_static( PARMS(Bit32u) ); + +#endif Index: root/xen-unstable.hg/tools/firmware/rombios/32bitgateway.c =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/firmware/rombios/32bitgateway.c @@ -0,0 +1,486 @@ +/* + * Implementation of a gateway into 32bit space. Stub functions + * can be called from Bochs BIOS which call functions with a compatible + * signature in 32bit space. All interrupts are disabled while in + * 32 bit mode. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Copyright (C) IBM Corporation, 2006 + * + * Author: Stefan Berger + */ + +/* + * Note: + * BCC's ABI does not require to preserve any 16bit registers ax, bx, cs, dx + * by a called function. So these registers need not be preserved while + * calling a function in 32bit space, either. + * + * When bcc calls a function with 16bit parameters it pushes 2 bytes onto + * the stack for such a parameter. GCC, however, expects 32bit parameters + * (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 + +#define START_PM_CODE USE32 +#define END_PM_CODE USE16 + +/* definition of used code/data segment descriptors */ +#define PM_NORMAL_CS (gdt_entry_pm_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) + + 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) + ; + ; preserves all registers and prepares cs, ds, es, ss for usage + ; in protected mode; while in prot.mode interrupts remain disabled +switch_to_protmode: + cli + + ; 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 + + 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 + and esp, #0xffff + xor eax, eax + mov ax, ss + rol eax, #4 + add eax, esp + mov esp, eax + + seg cs + lgdt my_gdtdesc ; switch to own table + + mov eax, cr0 + 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 + mov ss, ax + + pop eax ;@A2 + pop bp ;@A1 + ret + + END_PM_CODE + + + + .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, 0x9a, 0xcf, 0x00 + +gdt_entry_pm_16bit_cs: + ; temp. 16 bit code segment used while in protected mode + .word 0xffff, 0x0000 + .byte SEGMENT_OFFSET >> 16, 0x9a, 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, 0x92, 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 + ; restores all registers and prepares cs, es, ds, ss to be used + ; in real mode + 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 + push bp ;pop@A1 + mov bp, sp + push eax ;pop@X + + mov eax, [bp] ; return address low 16bits + ; and 'bp' are being moved + mov 2[bp], eax + + pop eax ;@X + add sp, #2 ; adjust stack for 'lost' bytes + + push eax ;pop@1 + push bx ;pop@2 + push si ;pop@3 + + 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: + mov eax, cr0 + 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 + + seg cs + lgdt realmode_gdtdesc + + sti ; allow interrupts + + pop si ;@3 + pop bx ;@2 + pop eax ;@1 + pop bp ;@A1 + + 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 +MEND + + +ASM_END + +#include "32bitprotos.h" +#include "32bitgateway.h" + +/******************************************************************** + Collection of stub functions for functions executed in 32bit space + *******************************************************************/ + +Bit32u multiply(a, b) /* for testing */ + Bit32u a; + Bit32u b; +{ + ASM_START + DoUpcall IDX_MULTIPLY + ASM_END +} + +Bit32u add(a, b) /* for testing */ + Bit32u a; + Bit32u b; +{ + ASM_START + DoUpcall IDX_ADD + ASM_END +} + +Bit32u set_static(a, b) /* for testing */ + Bit32u a; + Bit32u b; +{ + ASM_START + DoUpcall IDX_SET_STATIC + ASM_END +} + +/* a function to test the gateway */ +void +test_gateway() +{ + Bit32u res; + Bit16u err = 0; + + printf("32bit gateway "); + res = multiply(11111L,222L); + if (err = 0 && res != 11111L * 222L) { + printf("not working correctly: multiply\n"); + err = 1; + } + + res = add(111111L, 222222L); + if (err = 0 && res != 111111L + 222222L) { + printf("not working correctly: add\n"); + err = 1; + } + + res = set_static(0x12345678L); + if (err = 0 && res != 0x1L) { + printf("not working correctly: set_static (1)\n"); + err = 1; + } + res = set_static(0x11111111L); + if (err = 0 && res != 0x12345678L) { + printf("not working correctly: set_static (2)\n"); + err = 1; + } + + if (err == 0) { + printf("working correctly\n"); + } +} Index: root/xen-unstable.hg/tools/firmware/rombios/32bitgateway.h =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/firmware/rombios/32bitgateway.h @@ -0,0 +1,18 @@ +#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 Index: root/xen-unstable.hg/tools/firmware/hvmloader/mp_tables.c =================================================================== --- root.orig/xen-unstable.hg/tools/firmware/hvmloader/mp_tables.c +++ root/xen-unstable.hg/tools/firmware/hvmloader/mp_tables.c @@ -45,12 +45,6 @@ typedef unsigned long uint64_t; typedef signed long int64_t; #endif -#define ROMBIOS_SEG 0xF000 -#define ROMBIOS_BEGIN 0x000F0000 -#define ROMBIOS_SIZE 0x00010000 -#define ROMBIOS_MAXOFFSET 0x0000FFFF -#define ROMBIOS_END (ROMBIOS_BEGIN + ROMBIOS_SIZE) - /* number of non-processor MP table entries */ #define NR_NONPROC_ENTRIES 18 @@ -311,10 +305,7 @@ void* get_mp_table_start(void) bios_mem != (char *)ROMBIOS_END; bios_mem++ ) { - if ( bios_mem[0] == '_' && bios_mem[1] == '_' && - bios_mem[2] == '_' && bios_mem[3] == 'H' && - bios_mem[4] == 'V' && bios_mem[5] == 'M' && - bios_mem[6] == 'M' && bios_mem[7] == 'P' ) + if ( strncmp(bios_mem, "___HVMMP", 8) == 0) return bios_mem; } Index: root/xen-unstable.hg/tools/firmware/hvmloader/config.h =================================================================== --- root.orig/xen-unstable.hg/tools/firmware/hvmloader/config.h +++ root/xen-unstable.hg/tools/firmware/hvmloader/config.h @@ -11,4 +11,11 @@ #define PCI_ISA_DEVFN 0x08 /* dev 1, fn 0 */ #define PCI_ISA_IRQ_MASK 0x0c60U /* ISA IRQs 5,6,10,11 are PCI connected */ +#define ROMBIOS_SEG 0xF000 +#define ROMBIOS_BEGIN 0x000F0000 +#define ROMBIOS_SIZE 0x00010000 +#define ROMBIOS_MAXOFFSET 0x0000FFFF +#define ROMBIOS_END (ROMBIOS_BEGIN + ROMBIOS_SIZE) + + #endif /* __HVMLOADER_CONFIG_H__ */ Index: root/xen-unstable.hg/tools/firmware/rombios/Makefile =================================================================== --- root.orig/xen-unstable.hg/tools/firmware/rombios/Makefile +++ root/xen-unstable.hg/tools/firmware/rombios/Makefile @@ -12,7 +12,7 @@ clean: rm -f rombios*.txt rombios*.sym usage biossums rm -f BIOS-bochs-* -BIOS-bochs-latest: rombios.c biossums +BIOS-bochs-latest: rombios.c biossums 32bitgateway.c gcc -DBX_SMP_PROCESSORS=1 -E -P $< > _rombios_.c bcc -o rombios.s -C-c -D__i86__ -0 -S _rombios_.c sed -e 's/^\.text//' -e 's/^\.data//' rombios.s > _rombios_.s Index: root/xen-unstable.hg/tools/firmware/rombios/32bit/jumptable.h =================================================================== --- /dev/null +++ root/xen-unstable.hg/tools/firmware/rombios/32bit/jumptable.h @@ -0,0 +1,11 @@ +#ifndef JUMPTABLE_H +#define JUMPTABLE_H + +/* + name of the section the 32bit BIOS must have and where the array of + function poiners is built; hvmloader looks for this section and copies + it into the lower BIOS in the 0xf000 segment + */ +#define JUMPTABLE_SECTION_NAME ".biosjumptable" + +#endif Index: root/xen-unstable.hg/tools/firmware/hvmloader/util.c =================================================================== --- root.orig/xen-unstable.hg/tools/firmware/hvmloader/util.c +++ root/xen-unstable.hg/tools/firmware/hvmloader/util.c @@ -91,6 +91,15 @@ int strcmp(const char *cs, const char *c return res; } +int strncmp(const char *s1, const char *s2, uint32_t n) +{ + uint32_t ctr; + for (ctr = 0; ctr < n; ctr++) + if (s1[ctr] != s2[ctr]) + return (int)(s1[ctr] - s2[ctr]); + return 0; +} + void *memcpy(void *dest, const void *src, unsigned n) { int t0, t1, t2;