The attached patch implements support for the transparent call of functions in 32 bit space from 16 bit code and allows up to 6 parameters being passed to a 32 bit function. 3 of the parameters are passed via registers, the other ones via the stack. More parameters can be supported but would require additional code (afaik, there is not call for 'ret + %ecx' or equivalent replacement for 'ret + n' with dynamic n)
The core of the patch is in upcall.S where the assembly function is added that handles the transitioning and the passing of the parameters.
Each function in the 32 bit space that is supposed to be callable from 16 bit space requires an entry in upcall_protos.h, describing its index in the function call table, the numbers of parameters it takes and the parameter types themselves. These function entries are then differently expanded using #defines in the various files from which they are included and help to build function calls (the stubs in 16 bit space), the function call table in 32 bit space and declarations of prototypes to catch mismatch of parameters.
16 bit code that calls the 32 bit function is putting all parameters onto the stack but the #defines for 16 bit mode cause the function <function name>_upcall to be called, which is an assembly macro towards the end of upcall.S and prepares one more parameter in ebx to be passed to 'upcall'. The ebx register here holds the offset into the function call table in the lower 16 bits and the number of bytes that were put onto the stack when the function was called. The latter is necessary to fix up the stack in 'upcall' when parameters are passed via the stack so that the original caller sees the stack as if it had called the 32 bit function directly.
One test function test_highbios is being added that part 2 will then call from 16 bit space.
Signed-off-by: Stefan Berger stefanb@us.ibm.com
--- Makefile | 8 +- src/post.c | 4 + src/romlayout.S | 1 src/upcall.S | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/upcall.c | 22 +++++ src/upcall.h | 28 +++++++ src/upcall_16bit.c | 5 + src/upcall_protos.h | 14 +++ 8 files changed, 269 insertions(+), 4 deletions(-)
Index: seabios/src/upcall.c =================================================================== --- /dev/null +++ seabios/src/upcall.c @@ -0,0 +1,22 @@ +#include "config.h" // CONFIG_* +#include "util.h" +#include "types.h" +#include "upcall.h" + +int +test_highbios(u8 a, u16 b, u32 c, u8 d, u16 e, int f) +{ + dprintf(1,"test at %p\n",test_highbios); + dprintf(1,"a=%d,b=%d,c=%d,d=%d,e=%d,f=%d\n",a,b,c,d,e,f); + return a*b; +} + + +#define FUNC(IDX, NUMPARMS, RETTYPE, NAME, PARMS ...) \ + [IDX] = NAME, + +void *function_table[] = { +#include "upcall_protos.h" +}; + +#undef FUNC Index: seabios/src/upcall.h =================================================================== --- /dev/null +++ seabios/src/upcall.h @@ -0,0 +1,28 @@ +#ifndef UPCALL_H +#define UPCALL_H + +/* the actual jump table */ +extern void *function_table[]; + +# ifdef SIXTEENBIT + +# define FUNC(IDX, NUMPARMS, RETTYPE, NAME, PARMS...) \ + RETTYPE NAME ## _upcall(PARMS); + +# else + +# define FUNC(IDX, NUMPARMS, RETTYPE, NAME, PARMS ...) \ + RETTYPE NAME(PARMS); + +# endif + +#include "upcall_protos.h" +#undef FUNC + +/* + * holds the pointer where the function_table has been relocated to in + * the 'high bios' in 32 bit + */ +extern void *function_table_ptr VAR16VISIBLE; + +#endif /* UPCALL_H */ Index: seabios/src/upcall.S =================================================================== --- /dev/null +++ seabios/src/upcall.S @@ -0,0 +1,191 @@ +; .code16gcc + +// The maximum number of call parameters we can handle +// First 3 are passed via registers, the rest via stack +#define MAX_FUNC_ARGS 6 +#define MAX_ARG_BYTES ((MAX_FUNC_ARGS - 3) * 4) + +// Call a 32 bit function from 16bit mode via a stub in 16bit mode. +// Clobbers: ecx +// Result: eax + DECLFUNC upcall +upcall: + +#define CHUNK0 ( 4 ) /* for the already pushed %ebx in the macro */ + + pushl %esi // protect + + pushl %edx // 2nd parameter + pushl %eax // 1st parameter (will hold result) + pushl %ecx // 3rd parameter (clobbered) + + pushf +#define CHUNK1 (5 * 4) + + // Disable irqs (and clear direction flag) + cli + cld + + // Disable nmi + movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax + outb %al, $PORT_CMOS_INDEX + inb $PORT_CMOS_DATA, %al + + // enable a20 + inb $PORT_A20, %al + orb $A20_ENABLE_BIT, %al + outb %al, $PORT_A20 + + push %ds + push %es + push %esp +#define CHUNK2 (2 * 2 + 1 * 4) + + // assume ss = 0 + and $0xffff, %esp + + // Set segment descriptors + lidtw %cs:pmode_IDT_info + lgdtw %cs:rombios32_gdt_48 + + // Enable protected mode + movl %cr0, %eax + orl $CR0_PE, %eax + movl %eax, %cr0 + + ljmpl $SEG32_MODE32_CS, $(BUILD_BIOS_ADDR + 1f) + + .code32 +1: + // init data segments + movl $SEG32_MODE32_DS, %eax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw %ax, %fs + movw %ax, %gs + + // remember function index and num stack parms + pushl %ebx +#define CHUNK3 ( 4 ) + + // remember stackpointer to help against 'ret + n' + movl %esp, %esi + +#if MAX_ARG_BYTES > 0 + // Copy 32 bit aguments from original 16 bit call + movl $MAX_ARG_BYTES/4, %ecx +2: + pushl MAX_ARG_BYTES + CHUNK3 + CHUNK2 + CHUNK1 + CHUNK0(%esp) + loop 2b +#endif + + // call function in call table + mov (BUILD_BIOS_ADDR + function_table_ptr), %eax + + // add offset into table + and $0xffff, %ebx + add %eax, %ebx + + // load registers for register passing + movl MAX_ARG_BYTES + CHUNK3 + CHUNK2 +12(%esp), %edx + movl MAX_ARG_BYTES + CHUNK3 + CHUNK2 + 8(%esp), %eax + movl MAX_ARG_BYTES + CHUNK3 + CHUNK2 + 4(%esp), %ecx + + // call function + call *(%ebx) + + // Result to ecx + movl %eax, %ecx + + // load expected stack with all parameters undone + movl %esi, %esp + + // get previous ebx holding expected size of stack parms in upper + // 16 bit + popl %edx + shrl $16, %edx + + // Return to real mode + ljmpw $SEG32_MODE16_CS, $3f + + .code16gcc +3: + // Disable protected mode + movl %cr0, %eax + andl $~CR0_PE, %eax + movl %eax, %cr0 + + // far jump to flush CPU queue after transition to real mode + ljmpw $SEG_BIOS, $4f + +4: + // restore IDT to normal real-mode defaults + lidtw %cs:rmode_IDT_info + + // Clear segment registers + xorw %ax, %ax + movw %ax, %fs + movw %ax, %gs + movw %ax, %ss + + popl %esp + pop %es + pop %ds + popf + + // result to eax + mov %ecx, %eax + // expected size of stack parms into ecx + mov %edx, %ecx + + addl $8, %esp // skip ecx, eax + popl %edx + popl %esi + + popl %ebx // pushed by Upcall macro + + // caller expects us to undo stack parameters + cmpl $0x0, %ecx + jne 5f + retl // for 0,1,2,3 parameters + +5: + cmpl $0x4, %ecx + jne 6f + retl $0x4 // for 4 parameters + +6: + cmpl $0x8, %ecx + jne 7f + retl $0x8 // for 5 parameters + +7: +#if MAX_FUNC_ARGS > 6 +# error Need explicit code here to handle more parameters +#endif + retl $0xc // for 6 parameters + + +// The upcall macro loads ebx with the offset of the function call +// (in the function_table) into the lower 16 bits and loads the size of the +// parameters on the stack (beyond 3 parameters) into the upper 16 bits. + .macro doUpcall funcname idx numargs + DECLFUNC \funcname +\funcname: + pushl %ebx +.if \numargs > 3 + movl $(\idx << 2 + (\numargs-3) << 18),%ebx +.else + movl $(\idx << 2), %ebx +.endif + jmp upcall + .endm + + .code16gcc +#define FUNC(IDX, NUMPARMS, RETTYPE, NAME, PARMS ...) \ + doUpcall NAME ## _upcall IDX NUMPARMS + +#include "upcall_protos.h" + +#undef FUNC Index: seabios/src/upcall_protos.h =================================================================== --- /dev/null +++ seabios/src/upcall_protos.h @@ -0,0 +1,12 @@ +/* this file is included by multiple files and expands the #defines + differently each time */ + +#ifdef SIXTEENBIT + +/* all function names below must be expanded with _upcall */ + +# define test_highbios test_highbios_upcall + +#endif + +FUNC(0, 6, int , test_highbios, u8 a, u16 b, u32 c,u8 d, u16 e, int f) Index: seabios/src/upcall_16bit.c =================================================================== --- /dev/null +++ seabios/src/upcall_16bit.c @@ -0,0 +1,5 @@ +#include "config.h" // CONFIG_* +#include "types.h" + +/* anchor to high bios */ +void *function_table_ptr VAR16VISIBLE = NULL; Index: seabios/src/romlayout.S =================================================================== --- seabios.orig/src/romlayout.S +++ seabios/src/romlayout.S @@ -19,6 +19,7 @@ #include "cmos.h" // CMOS_RESET_CODE #include "../out/asm-offsets.h" // BREGS_* #include "entryfuncs.S" // ENTRY_* +#include "upcall.S"
/**************************************************************** Index: seabios/src/post.c =================================================================== --- seabios.orig/src/post.c +++ seabios/src/post.c @@ -24,6 +24,7 @@ #include "paravirt.h" // qemu_cfg_port_probe #include "ps2port.h" // ps2port_setup #include "virtio-blk.h" // virtio_blk_setup +#include "upcall.h" // function_table
/**************************************************************** @@ -307,6 +308,9 @@ reloc_init(void) dprintf(1, "Relocating init from %p to %p (size %d)\n" , code32init_start, dest, initsize); s32 delta = dest - (void*)code32init_start; + + function_table_ptr = (void *)&function_table + delta; + memcpy(dest, code32init_start, initsize); updateRelocs(dest, _reloc_abs_start, _reloc_abs_end, delta); updateRelocs(dest, _reloc_rel_start, _reloc_rel_end, -delta); Index: seabios/Makefile =================================================================== --- seabios.orig/Makefile +++ seabios/Makefile @@ -16,11 +16,11 @@ SRCBOTH=misc.c pmm.c stacks.c output.c u pnpbios.c pirtable.c vgahooks.c ramdisk.c pcibios.c blockcmd.c \ usb.c usb-uhci.c usb-ohci.c usb-ehci.c usb-hid.c usb-msc.c \ virtio-ring.c virtio-pci.c virtio-blk.c apm.c -SRC16=$(SRCBOTH) system.c disk.c font.c +SRC16=$(SRCBOTH) system.c disk.c font.c upcall_16bit.c SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \ acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \ lzmadecode.c bootsplash.c jpeg.c usb-hub.c paravirt.c dev-i440fx.c \ - pci_region.c + pci_region.c upcall.c SRC32SEG=util.c output.c pci.c pcibios.c apm.c stacks.c
cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \ @@ -39,11 +39,11 @@ COMMONCFLAGS += $(call cc-option,$(CC),- COMMONCFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,)
CFLAGS32FLAT = $(COMMONCFLAGS) -g -DMODE16=0 -DMODESEGMENT=0 -CFLAGSSEG = $(COMMONCFLAGS) -DMODESEGMENT=1 -fno-defer-pop \ +CFLAGSSEG = $(COMMONCFLAGS) -DMODESEGMENT=1 -DSIXTEENBIT -fno-defer-pop \ $(call cc-option,$(CC),-fno-jump-tables,-DMANUAL_NO_JUMP_TABLE) \ $(call cc-option,$(CC),-fno-tree-switch-conversion,) CFLAGS32SEG = $(CFLAGSSEG) -DMODE16=0 -g -CFLAGS16INC = $(CFLAGSSEG) -DMODE16=1 \ +CFLAGS16INC = $(CFLAGSSEG) -DMODE16=1 -DSIXTEENBIT \ $(call cc-option,$(CC),--param large-stack-frame=4,-fno-inline) CFLAGS16 = $(CFLAGS16INC) -g
On 11/22/2010 09:08 AM, Stefan Berger wrote:
// enable a20
inb $PORT_A20, %al
orb $A20_ENABLE_BIT, %al
outb %al, $PORT_A20
Let me *strongly* recommend isolate A20M handling in a single module for the following reasons:
1. it is necessary to handle INT 15h, AX=2400/2401h; 2. different platforms have different requirements (port 92h is not universally supported) and even if it is the amount of time until it is active varies; 3. some newer CPUs (e.g. Core i3/5/7) don't even have A20M so there is absolutely no reason to waste time poking it at all; 4. testing for A20M active may be advisable for speed purposes.
-hpa
On Mon, Nov 22, 2010 at 12:08:33PM -0500, Stefan Berger wrote:
The attached patch implements support for the transparent call of functions in 32 bit space from 16 bit code and allows up to 6
[...]
// Disable irqs (and clear direction flag)
cli
cld
// Disable nmi
movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
outb %al, $PORT_CMOS_INDEX
inb $PORT_CMOS_DATA, %al
// enable a20
inb $PORT_A20, %al
orb $A20_ENABLE_BIT, %al
outb %al, $PORT_A20
It should be possible to extend call32() to do what you need - duplicating this functionality is a non-starter.
-Kevin
On Mon, Nov 22, 2010 at 07:40:36PM -0500, Kevin O'Connor wrote:
It should be possible to extend call32() to do what you need -
FYI - here's what call32 extended to pass a parameter looks like:
--- a/src/stacks.c +++ b/src/stacks.c @@ -37,14 +37,14 @@ static inline void lgdt(struct descloc_s *desc) { }
// Call a 32bit SeaBIOS function from a 16bit SeaBIOS function. -static inline int -call32(void *func) +static inline u32 +call32(void *func, u32 eax, u32 errret) { ASSERT16(); u32 cr0 = getcr0(); if (cr0 & CR0_PE) // Called in 16bit protected mode?! - return -1; + return errret;
// Backup cmos index register and disable nmi u8 cmosindex = inb(PORT_CMOS_INDEX); @@ -69,7 +69,7 @@ call32(void *func) " pushl $(" __stringify(BUILD_BIOS_ADDR) " + 1f)\n" " jmp transition32\n" " .code32\n" - "1:calll *%2\n" + "1:calll *%3\n" " pushl $2f\n" " jmp transition16big\n"
@@ -78,9 +78,9 @@ call32(void *func) "2:movl %0, %%ds\n" " movl %0, %%ss\n" " movl %1, %%esp\n" - : "=&r" (bkup_ss), "=&r" (bkup_esp) + : "=&r" (bkup_ss), "=&r" (bkup_esp), "+a" (eax) : "r" (func) - : "eax", "ecx", "edx", "cc", "memory"); + : "ecx", "edx", "cc", "memory");
// Restore gdt and fs/gs lgdt(&gdt); @@ -90,7 +90,7 @@ call32(void *func) // Restore cmos index register outb(cmosindex, PORT_CMOS_INDEX); inb(PORT_CMOS_DATA); - return 0; + return eax; }
// 16bit trampoline for enabling irqs from 32bit mode. @@ -393,5 +393,5 @@ check_preempt(void) || GET_FLATPTR(MainThread.next) == &MainThread) return;
- call32(yield_preempt); + call32(yield_preempt, 0, 0); }
-Kevin
On 11/23/10 02:13, Kevin O'Connor wrote:
On Mon, Nov 22, 2010 at 07:40:36PM -0500, Kevin O'Connor wrote:
It should be possible to extend call32() to do what you need -
FYI - here's what call32 extended to pass a parameter looks like:
--- a/src/stacks.c +++ b/src/stacks.c @@ -37,14 +37,14 @@ static inline void lgdt(struct descloc_s *desc) { }
// Call a 32bit SeaBIOS function from a 16bit SeaBIOS function. -static inline int -call32(void *func) +static inline u32 +call32(void *func, u32 eax, u32 errret)
Tried to use that (see patch). Failed. When calling pci_readl from real mode I see the pci_readl debug printf but not the one from pci_readl_32 ...
cheers, Gerd
On Tue, Nov 23, 2010 at 11:32:13AM +0100, Gerd Hoffmann wrote:
On 11/23/10 02:13, Kevin O'Connor wrote:
On Mon, Nov 22, 2010 at 07:40:36PM -0500, Kevin O'Connor wrote:
It should be possible to extend call32() to do what you need -
FYI - here's what call32 extended to pass a parameter looks like:
--- a/src/stacks.c +++ b/src/stacks.c @@ -37,14 +37,14 @@ static inline void lgdt(struct descloc_s *desc) { }
// Call a 32bit SeaBIOS function from a 16bit SeaBIOS function. -static inline int -call32(void *func) +static inline u32 +call32(void *func, u32 eax, u32 errret)
Tried to use that (see patch). Failed. When calling pci_readl from real mode I see the pci_readl debug printf but not the one from pci_readl_32 ...
You need to make sure the 32bit function is only available in 32bit mode. See below.
I briefly tested this and the call completes, but it caused issues with bootup - I'm not sure if this is due to a bug somewhere or due to 32bit mode switching being inherently unsafe.
-Kevin
--- a/src/stacks.c +++ b/src/stacks.c @@ -395,3 +395,28 @@ check_preempt(void)
call32(yield_preempt, 0, 0); } + +extern u32 pci_readl_32(u32 addr); +#if MODESEGMENT == 0 +u32 VISIBLE32FLAT +pci_readl_32(u32 addr) +{ + dprintf(1, "pci rd32: %x\n", addr); + return readl((void*)addr); +} +#endif + +u32 pci_readl(u32 addr) +{ + dprintf(1, "pci read: %x\n", addr); + if (MODESEGMENT) + return call32(pci_readl_32, addr, -1); + return pci_readl_32(addr); +} + +void pci_writel(u32 addr, u32 val) +{ + dprintf(1, "pci write: %x, %x\n", addr, val); + if (!MODESEGMENT) + writel((void*)addr, val); +}
On 11/23/10 14:24, Kevin O'Connor wrote:
On Tue, Nov 23, 2010 at 11:32:13AM +0100, Gerd Hoffmann wrote: You need to make sure the 32bit function is only available in 32bit mode. See below.
Hmm, still not working for me.
Is there some way to look at the code generated by gcc? Trying 'objdump -d code16.o' looks bogous (16 vs 32bit issue?)
cheers, Gerd
On 11/23/2010 08:54 AM, Gerd Hoffmann wrote:
On 11/23/10 14:24, Kevin O'Connor wrote:
On Tue, Nov 23, 2010 at 11:32:13AM +0100, Gerd Hoffmann wrote: You need to make sure the 32bit function is only available in 32bit mode. See below.
Hmm, still not working for me.
Is there some way to look at the code generated by gcc? Trying 'objdump -d code16.o' looks bogous (16 vs 32bit issue?)
There should be a ccode.16.s.
Otherwise you could capture the cc command when using
V=1 make
change the -c to -S and have a look at the generated output.
Stefan
cheers, Gerd
On Tue, Nov 23, 2010 at 02:54:57PM +0100, Gerd Hoffmann wrote:
On 11/23/10 14:24, Kevin O'Connor wrote:
On Tue, Nov 23, 2010 at 11:32:13AM +0100, Gerd Hoffmann wrote: You need to make sure the 32bit function is only available in 32bit mode. See below.
Hmm, still not working for me.
Is there some way to look at the code generated by gcc? Trying 'objdump -d code16.o' looks bogous (16 vs 32bit issue?)
I use:
objdump -m i386 -M i8086 -M suffix -ldr out/code16.o
-Kevin
On Tue, Nov 23, 2010 at 08:30:24PM -0500, Kevin O'Connor wrote:
On Tue, Nov 23, 2010 at 02:54:57PM +0100, Gerd Hoffmann wrote:
On 11/23/10 14:24, Kevin O'Connor wrote:
On Tue, Nov 23, 2010 at 11:32:13AM +0100, Gerd Hoffmann wrote: You need to make sure the 32bit function is only available in 32bit mode. See below.
Hmm, still not working for me.
Looks like call32 doesn't work when %esp>64K. I hacked a patch (see below), but it's quite ugly.
Is there some way to look at the code generated by gcc? Trying 'objdump -d code16.o' looks bogous (16 vs 32bit issue?)
I use:
objdump -m i386 -M i8086 -M suffix -ldr out/code16.o
Actually, this is a little more useful:
objdump -m i386 -M i8086 -M suffix -ldr out/rom16.o
-Kevin
diff --git a/src/romlayout.S b/src/romlayout.S index a469596..bea7509 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -130,7 +130,10 @@ transition16big: movw %ax, %ss // Assume stack is in segment 0
movl %ecx, %eax - retl + //retl + movl (%esp), %ecx + addl $4, %esp + jmpl *%ecx
// Call a 16bit function from 16bit mode with a specified cpu register state // %eax = address of struct bregs diff --git a/src/stacks.c b/src/stacks.c index 7db0e3c..620086b 100644 --- a/src/stacks.c +++ b/src/stacks.c @@ -56,17 +56,18 @@ call32(void *func, u32 eax, u32 errret) struct descloc_s gdt; sgdt(&gdt);
- u32 bkup_ss, bkup_esp; + u32 bkup_ss, bkup_esp = 0; asm volatile( // Backup ss/esp / set esp to flat stack location + " pushl $(" __stringify(BUILD_BIOS_ADDR) " + 1f)\n" " movl %%ss, %0\n" + " movl %1, %%ss\n" " movl %%esp, %1\n" " shll $4, %0\n" " addl %0, %%esp\n" - " movl %%ss, %0\n" + " shrl $4, %0\n"
// Transition to 32bit mode, call func, return to 16bit - " pushl $(" __stringify(BUILD_BIOS_ADDR) " + 1f)\n" " jmp transition32\n" " .code32\n" "1:calll *%3\n" @@ -78,7 +79,8 @@ call32(void *func, u32 eax, u32 errret) "2:movl %0, %%ds\n" " movl %0, %%ss\n" " movl %1, %%esp\n" - : "=&r" (bkup_ss), "=&r" (bkup_esp), "+a" (eax) + " popl %1\n" + : "=&r" (bkup_ss), "+r" (bkup_esp), "+a" (eax) : "r" (func) : "ecx", "edx", "cc", "memory");
@@ -395,3 +397,28 @@ check_preempt(void)
call32(yield_preempt, 0, 0); } + +extern u32 pci_readl_32(u32 addr); +#if MODESEGMENT == 0 +u32 VISIBLE32FLAT +pci_readl_32(u32 addr) +{ + dprintf(1, "pci rd32: %x\n", addr); + return readl((void*)addr); +} +#endif + +u32 pci_readl(u32 addr) +{ + dprintf(1, "pci read: %x\n", addr); + if (MODESEGMENT) + return call32(pci_readl_32, addr, -1); + return pci_readl_32(addr); +} + +void pci_writel(u32 addr, u32 val) +{ + dprintf(1, "pci write: %x, %x\n", addr, val); + if (!MODESEGMENT) + writel((void*)addr, val); +}
Hi,
Looks like call32 doesn't work when %esp>64K. I hacked a patch (see below), but it's quite ugly.
Does the trick though, at least for grub/syslinux booting from ahci.
http://cgit.freedesktop.org/~kraxel/seabios/log/?h=ahci
cheers, Gerd
On Wed, Nov 24, 2010 at 12:41:20PM +0100, Gerd Hoffmann wrote:
Hi,
Looks like call32 doesn't work when %esp>64K. I hacked a patch (see below), but it's quite ugly.
Does the trick though, at least for grub/syslinux booting from ahci.
Very nice!
I'll cleanup the call32 changes.
-Kevin
On Wed, Nov 24, 2010 at 08:09:26AM -0500, Kevin O'Connor wrote:
On Wed, Nov 24, 2010 at 12:41:20PM +0100, Gerd Hoffmann wrote:
Hi,
Looks like call32 doesn't work when %esp>64K. I hacked a patch (see below), but it's quite ugly.
Does the trick though, at least for grub/syslinux booting from ahci.
Very nice!
Great stuff :-)
Gerd Hoffmann wrote:
Hi,
Looks like call32 doesn't work when %esp>64K. I hacked a patch (see below), but it's quite ugly.
Does the trick though, at least for grub/syslinux booting from ahci.
http://cgit.freedesktop.org/~kraxel/seabios/log/?h=ahci
cheers, Gerd
Should the pci scan in ahci_init() be replaced by an entry in pci_class_tbl?
Should the "for (pnr = 0; pnr < 32; pnr++)" loop in ahci_detect() use the "Number of Ports" value from ctrl->cap instead of 32?
Sebastian
On 11/24/10 19:34, Sebastian Herbszt wrote:
Gerd Hoffmann wrote:
Hi,
Looks like call32 doesn't work when %esp>64K. I hacked a patch (see below), but it's quite ugly.
Does the trick though, at least for grub/syslinux booting from ahci.
http://cgit.freedesktop.org/~kraxel/seabios/log/?h=ahci
cheers, Gerd
Should the pci scan in ahci_init() be replaced by an entry in pci_class_tbl?
I don't think so. That looks like being intended for device specific tweaks in early pci init.
Should the "for (pnr = 0; pnr < 32; pnr++)" loop in ahci_detect() use the "Number of Ports" value from ctrl->cap instead of 32?
Would safe a few loop hops but isn't required. Each usable port is flagged with a bit in ctrl->ports.
cheers, Gerd
Gerd Hoffmann wrote:
On 11/24/10 19:34, Sebastian Herbszt wrote:
Gerd Hoffmann wrote:
Hi,
Looks like call32 doesn't work when %esp>64K. I hacked a patch (see below), but it's quite ugly.
Does the trick though, at least for grub/syslinux booting from ahci.
http://cgit.freedesktop.org/~kraxel/seabios/log/?h=ahci
cheers, Gerd
Should the pci scan in ahci_init() be replaced by an entry in pci_class_tbl?
I don't think so. That looks like being intended for device specific tweaks in early pci init.
I think some ICH registers should be programmed by the BIOS. So at least that part should be device specific.
Sebastian
seabios-bounces@seabios.org wrote on 11/22/2010 07:40:36 PM:
Cc:
seabios
On Mon, Nov 22, 2010 at 12:08:33PM -0500, Stefan Berger wrote:
The attached patch implements support for the transparent call of functions in 32 bit space from 16 bit code and allows up to 6
[...]
// Disable irqs (and clear direction flag)
cli
cld
// Disable nmi
movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
outb %al, $PORT_CMOS_INDEX
inb $PORT_CMOS_DATA, %al
// enable a20
inb $PORT_A20, %al
orb $A20_ENABLE_BIT, %al
outb %al, $PORT_A20
It should be possible to extend call32() to do what you need - duplicating this functionality is a non-starter.
Yes, this block is duplicated, but the code around it is different than what exists.
Would you want the same type of transparency in the code, i.e., using the function tables and the tricks with the #defines? Either way is fine, but it gives me direction on how to proceed.
Stefan