OSDev.org
https://forum.osdev.org/

Question about libx86emu
https://forum.osdev.org/viewtopic.php?f=1&t=31388
Page 1 of 2

Author:  Agola [ Sun Feb 26, 2017 11:20 am ]
Post subject:  Question about libx86emu

Sorry for that silly question.

Hi, I was making an emulator to use BIOS functions in long / protected mode. After all of my attempts fail (code was unstable and really very very messy) I decided to use libx86emu or x86emu.
The sad part is I can't find any download links for it. All links I've found from the Google are broken.

Then I found libx86emu from opensuse repo and https://github.com/wfeldt/libx86emu, but it compiles as a shared library. My OS doesn't support dynamically linked libraries, and I don't know how to patch makefile to build it as a static library, simply an .a archive. Then I found x86emu from archive.org, part of Exclaim project, by Adam Smith. But it looks really old and some part of code is missing.

Where can I found the x86emu / x86emu or how can I patch libx86emu Makefile to build as a static library?

Makefile:

Code:
ARCH   := $(shell uname -m)
ifneq ($(filter i386 i486 i586 i686, $(ARCH)),)
ARCH   := i386
endif

GIT2LOG := $(shell if [ -x ./git2log ] ; then echo ./git2log --update ; else echo true ; fi)
GITDEPS := $(shell [ -d .git ] && echo .git/HEAD .git/refs/heads .git/refs/tags)
VERSION := $(shell $(GIT2LOG) --version VERSION ; cat VERSION)
BRANCH  := $(shell [ -d .git ] && git branch | perl -ne 'print $$_ if s/^\*\s*//')
PREFIX  := libx86emu-$(VERSION)

MAJOR_VERSION := $(shell $(GIT2LOG) --version VERSION ; cut -d . -f 1 VERSION)

CC   = gcc
CFLAGS   = -g -O2 -fPIC -fomit-frame-pointer -Wall
ifneq ($(filter x86_64, $(ARCH)),)
LIBDIR   = /usr/lib64
else
LIBDIR   = /usr/lib
endif
LIBX86   = libx86emu

CFILES   = $(wildcard *.c)
OBJS   = $(CFILES:.c=.o)

LIB_NAME   = $(LIBX86).so.$(VERSION)
LIB_SONAME   = $(LIBX86).so.$(MAJOR_VERSION)

.PHONY: all shared install test clean

%.o: %.c
   $(CC) -c $(CFLAGS) $<

all: changelog shared

changelog: $(GITDEPS)
   $(GIT2LOG) --changelog changelog

shared: $(LIB_NAME)

install: shared
   install -D $(LIB_NAME) $(DESTDIR)$(LIBDIR)/$(LIB_NAME)
   ln -snf $(LIB_NAME) $(DESTDIR)$(LIBDIR)/$(LIB_SONAME)
   ln -snf $(LIB_SONAME) $(DESTDIR)$(LIBDIR)/$(LIBX86).so
   install -m 644 -D include/x86emu.h $(DESTDIR)/usr/include/x86emu.h

$(LIB_NAME): .depend $(OBJS)
   $(CC) -shared -Wl,-soname,$(LIB_SONAME) $(OBJS) -o $(LIB_NAME)

test:
   make -C test

archive: changelog
   @if [ ! -d .git ] ; then echo no git repo ; false ; fi
   mkdir -p package
   git archive --prefix=$(PREFIX)/ $(BRANCH) > package/$(PREFIX).tar
   tar -r -f package/$(PREFIX).tar --mode=0664 --owner=root --group=root --mtime="`git show -s --format=%ci`" --transform='s:^:$(PREFIX)/:' VERSION changelog
   xz -f package/$(PREFIX).tar

clean:
   make -C test clean
   rm -f *.o *~ include/*~ *.so.* .depend
   rm -rf package

ifneq "$(MAKECMDGOALS)" "clean"
.depend: $(CFILES)
   @$(CC) -MG -MM $(CFLAGS) $(CFILES) >$@
-include .depend
endif


Thanks in advance.

Author:  Ch4ozz [ Sun Feb 26, 2017 11:31 am ]
Post subject:  Re: I can't find libx86emu or x86emu

No need to compile this at all beforehand, just copy all the code into your os tree and include the headers and link it with the rest of the os.
Anyways, if you still want to build this externally use -static.
It will tell the linker to link it as static library (.a) instead of a shared one (.so)

Author:  Agola [ Sun Feb 26, 2017 12:56 pm ]
Post subject:  Re: I can't find libx86emu or x86emu

Thanks, I fixed by compiling until the part of dynamic library creation, then created the static library manually with i686-agola-ar rcs ...

Except, a new problem. I couldn't find a way to redirect virtual port / memory io to real port / memory io. BIOS code works in VM and returns with a success code, but it doesn't affect the real system.
How can I redirect the port and mem io to real mem and ports?

The nearest thing for it:

Code:
x86emu_memio_handler_t x86emu_set_memio_handler(x86emu_t *emu, x86emu_memio_handler_t handler);
typedef unsigned (* x86emu_memio_handler_t)(x86emu_t *emu, u32 addr, u32 *val, unsigned type);


Thanks in advance.

Author:  onlyonemac [ Sun Feb 26, 2017 2:17 pm ]
Post subject:  Re: I can't find libx86emu or x86emu

x86emu is an x86 emulator. It's designed to simulate an x86 system, like a virtual machine. It's not intended for executing BIOS functions on your real CPU.

Author:  Agola [ Sun Feb 26, 2017 2:25 pm ]
Post subject:  Re: I can't find libx86emu or x86emu

Yes, x86emu is an emulator. And I want to use it to execute BIOS' code. I simply copy the lowest 1 MB of memory to virtual machine's memory, then make cs:ip point to 0:7C00 where I simply put the opcode of execute int 0x10. It should work, isn't it?

This is how I done it:

Code:
    x86emu_t *emu = x86emu_new(X86EMU_PERM_RWX, X86EMU_PERM_RWX);
    x86emu_set_log(emu, 0xFFFFFF, flush_log);

    vm_write_nbytes(emu, 4, 4, 0x100000 - 4, X86EMU_PERM_RWX | X86EMU_PERM_VALID);

    x86emu_set_perm(emu, 4, 0xFFFFFF, X86EMU_PERM_RWX | X86EMU_PERM_VALID);
    x86emu_set_io_perm(emu, 4, 0xFFFFFF, X86EMU_PERM_RWX | X86EMU_PERM_VALID);

    x86emu_set_seg_register(emu, emu->x86.R_CS_SEL, 0);
    emu->x86.R_EIP = 0x7c00;

    vm_write_byte(emu, 0x7c00, 0xfb, X86EMU_PERM_RWX | X86EMU_PERM_VALID); //sti
    vm_write_word(emu, 0x7c01, 0x10cd, X86EMU_PERM_RWX | X86EMU_PERM_VALID); //int 0x10
    vm_write_byte(emu, 0x7c03, 0xf4, X86EMU_PERM_RWX | X86EMU_PERM_VALID); //hlt

    emu->x86.R_AX = 0x4F02;
    emu->x86.R_BX = 0x4117;

    x86emu_run(emu, X86EMU_RUN_LOOP);

    printf("ax: 0x%X", emu->x86.R_AX);


Output is ax: 0x4F, so it really does the mode switching in its virtual memory and port io. Then I want to redirect it to real memory and ports to make it "really" happened.
It should be possible, as there are many people used that way.

Thanks in advance.

Author:  Ch4ozz [ Sun Feb 26, 2017 4:16 pm ]
Post subject:  Re: I can't find libx86emu or x86emu

Well, it will only emulate everything you put in, it will never switch the resolution for example using VESA functions, I doubt you will be able to redirect everything perfectly though.
What your looking for is either Virtual 8086 Mode (http://wiki.osdev.org/Virtual_8086_Mode) which I wouldnt use or a switch to realmode and back to protected mode like this: http://www.rohitab.com/discuss/topic/35 ... cted-mode/

Author:  Octocontrabass [ Sun Feb 26, 2017 4:55 pm ]
Post subject:  Re: I can't find libx86emu or x86emu

I'm not sure why everyone keeps saying you can't use x86emu to change the screen resolution. That's exactly what X.Org Server does with its copy of x86emu.

...Unfortunately, I couldn't figure out how it sets up the I/O callbacks to allow the emulated code to communicate with hardware. All I could find was the code to emulate things the video card ROM might try to access that it shouldn't be able to, like the PIT and the PCI configuration registers.

Author:  dchapiesky [ Sun Feb 26, 2017 7:22 pm ]
Post subject:  Re: I can't find libx86emu or x86emu

Octocontrabass wrote:
I'm not sure why everyone keeps saying you can't use x86emu to change the screen resolution. That's exactly what X.Org Server does with its copy of x86emu.

...Unfortunately, I couldn't figure out how it sets up the I/O callbacks to allow the emulated code to communicate with hardware. All I could find was the code to emulate things the video card ROM might try to access that it shouldn't be able to, like the PIT and the PCI configuration registers.



https://github.com/XQuartz/xorg-server/ ... NT10.HOWTO

and the whole int10 directory....

particularly MapCurrentInt10() in helper_exec.c....

which links to (in linux) https://github.com/XQuartz/xorg-server/ ... 10/linux.c

which shows how realmode memory of the emulator is mapped via mmap to the proper addresses of the physical hardware....

I would use the stub code in https://github.com/XQuartz/xorg-server/ ... pport/stub

cheers

Author:  Agola [ Mon Feb 27, 2017 9:16 am ]
Post subject:  Re: I can't find libx86emu or x86emu

I found x86emu from X.org, copyrighted to SciTech Software.

And it worked!
After memory and port io hooks, it has successfully set the mode. I also tried other BIOS interrupts, all worked.

I think that is the best way for BIOS interrupts, it works both on protected and long mode, fast and portable.

That is code:

Code:
    portfuncs.outb = (void*) outb;
    portfuncs.outw = (void*) outw;
    portfuncs.outl = (void*) outl;
    portfuncs.inb = (void*) inb;
    portfuncs.inw = (void*) inw;
    portfuncs.inl = (void*) inl;

    memfuncs.rdb = (void*) mem_read_byte;
    memfuncs.rdw = (void*) mem_read_word;
    memfuncs.rdl = (void*) mem_read_long;
    memfuncs.wrb = (void*) mem_write_byte;
    memfuncs.wrw = (void*) mem_write_word;
    memfuncs.wrl = (void*) mem_write_long;

    memset(&M, 0, sizeof(M));

    X86EMU_setupMemFuncs(&memfuncs);
    X86EMU_setupPioFuncs(&portfuncs);

    M.x86.gen.A.I16_reg.x_reg = 0x4F02;
    M.x86.gen.B.I16_reg.x_reg = 0x4107;

    X86EMU_prepareForInt(0x10);
   
    X86EMU_exec();


And that is the screenshot

Image


But, it is really old. Modern version of x86emu is libx86emu, used by openSUSE and hwinfo. And I want to use it instead of x86emu.

And, it is hard to set up its memory and port io hook.

https://github.com/wfeldt/libx86emu#x86 ... _handler_t is way to do it, and I've almost finished it.

X86EMU_MEMIO_R is read from memory,
X86EMU_MEMIO_W is write to memory,
X86EMU_MEMIO_I is read from port,
X86EMU_MEMIO_O is write to port.

But what is X86EMU_MEMIO_X? Everything works except that.

I couldn't understand what is X86EMU_MEMIO_X for, and it gets called many times, so I need to implement it, too.

Thanks in advance.

Author:  Korona [ Mon Feb 27, 2017 10:04 am ]
Post subject:  Re: I can't find libx86emu or x86emu

A quick search in the GitHub repository reveals that X86EMU_MEMIO_X is an instruction fetch, that means it has the same semantics as X86EMU_MEMIO_R. (But be aware that I did not actually try that library)

Note that the BIOS was never meant to be used alongside a real OS and I'm sure that things will break spectacularly if you're not very careful. For example I would ensure that only a single instance of this emulator runs at a time and that no ports and MMIO regions that the emulator accesses are read/written by real drivers at the same time. You probably also have to be careful not to change PCI configuration space concurrently and ensure that all expansion ROM mappings are in the same state as they where when BIOS ran.

Author:  Agola [ Mon Feb 27, 2017 11:05 am ]
Post subject:  Re: I can't find libx86emu or x86emu

Korona wrote:
A quick search in the GitHub repository reveals that X86EMU_MEMIO_X is an instruction fetch, that means it has the same semantics as X86EMU_MEMIO_R. (But be aware that I did not actually try that library)

Note that the BIOS was never meant to be used alongside a real OS and I'm sure that things will break spectacularly if you're not very careful. For example I would ensure that only a single instance of this emulator runs at a time and that no ports and MMIO regions that the emulator accesses are read/written by real drivers at the same time. You probably also have to be careful not to change PCI configuration space concurrently and ensure that all expansion ROM mappings are in the same state as they where when BIOS ran.


Thanks, I changed X86EMU_MEMIO_X to same as X86EMU_MEMIO_R, but it is not working.
Maybe I'm mishandling inputs / outputs, as libx86emu has a different, paged memory system in mem.c that I don't fully understand.

How can I handle the input / outputs with x86emu_set_memio_handler?
And is it the correct way to handle IO and redirect IO to real machine?

Thanks in advance.

Author:  dchapiesky [ Mon Feb 27, 2017 11:43 am ]
Post subject:  Re: I can't find libx86emu or x86emu

Agola wrote:
How can I handle the input / outputs with x86emu_set_memio_handler?
And is it the correct way to handle IO and redirect IO to real machine?



The handler you pass to x86emu_set_memio_handler takes an argument called "type"

you do a switch/case statement against the following possible values:

Code:

X86EMU_MEMIO_8 + X86EMU_MEMIO_R
X86EMU_MEMIO_16 + X86EMU_MEMIO_R
X86EMU_MEMIO_32 + X86EMU_MEMIO_R
X86EMU_MEMIO_8_NOPERM + X86EMU_MEMIO_R

X86EMU_MEMIO_8 + X86EMU_MEMIO_W
X86EMU_MEMIO_16 + X86EMU_MEMIO_W
X86EMU_MEMIO_32 + X86EMU_MEMIO_W
X86EMU_MEMIO_8_NOPERM + X86EMU_MEMIO_W

X86EMU_MEMIO_8 + X86EMU_MEMIO_X
X86EMU_MEMIO_16 + X86EMU_MEMIO_X
X86EMU_MEMIO_32 + X86EMU_MEMIO_X
X86EMU_MEMIO_8_NOPERM + X86EMU_MEMIO_X

X86EMU_MEMIO_8 + X86EMU_MEMIO_I
X86EMU_MEMIO_16 + X86EMU_MEMIO_I
X86EMU_MEMIO_32 + X86EMU_MEMIO_I
X86EMU_MEMIO_8_NOPERM + X86EMU_MEMIO_I

X86EMU_MEMIO_8 + X86EMU_MEMIO_O
X86EMU_MEMIO_16 + X86EMU_MEMIO_O
X86EMU_MEMIO_32 + X86EMU_MEMIO_O
X86EMU_MEMIO_8_NOPERM + X86EMU_MEMIO_O



if you look at decode.c you see that it uses X86EMU_MEMIO_* to determine how to cast a particular address.... I would definitely turn on logging so decode.c shows you what is happening...

Author:  Agola [ Mon Feb 27, 2017 1:35 pm ]
Post subject:  Re: I can't find libx86emu or x86emu

Yay!

Finally, it works with new version, libx86emu also.
All interrupts I tried worked, but not important for me as I will just use some int 0x10 functions :P

That is the code:

Code:
unsigned alternate_vm_memio(x86emu_t *emu, uint32_t addr, uint32_t *val, uint32_t type)
{
  x86emu_mem_t *mem = emu->mem;

  uint32_t bits = type & 0xFF;
  type &= ~0xFF;

  mem->invalid = 0;

  switch(type)
  {
    case X86EMU_MEMIO_R:
      switch(bits)
      {
        case X86EMU_MEMIO_8:
          *val = mem_read_byte(addr);
          break;
        case X86EMU_MEMIO_16:
          *val = mem_read_word(addr);
          break;
        case X86EMU_MEMIO_32:
          *val = mem_read_long(addr);
          break;
        case X86EMU_MEMIO_8_NOPERM:
          *val = mem_read_byte(addr);
          break;
      }
      break;

    case X86EMU_MEMIO_W:
      switch(bits)
      {
        case X86EMU_MEMIO_8:
          mem_write_byte(addr, *val);
          break;
        case X86EMU_MEMIO_16:
          mem_write_word(addr, *val);
          break;
        case X86EMU_MEMIO_32:
          mem_write_long(addr, *val);
          break;
        case X86EMU_MEMIO_8_NOPERM:
          mem_write_byte(addr, *val);
          break;
      }
      break;

    case X86EMU_MEMIO_X:
      switch(bits)
      {
        case X86EMU_MEMIO_8:
          *val = mem_read_byte(addr);
          break;
        case X86EMU_MEMIO_16:
          *val = mem_read_word(addr);
          break;
        case X86EMU_MEMIO_32:
          *val = mem_read_long(addr);
          break;
      }
      break;

    case X86EMU_MEMIO_I:
      switch(bits)
      {
        case X86EMU_MEMIO_8:
          *val = inb(addr);
          break;
        case X86EMU_MEMIO_16:
          *val = inw(addr);
          break;
        case X86EMU_MEMIO_32:
          *val = inl(addr);
          break;
      }
      break;

    case X86EMU_MEMIO_O:
      switch(bits)
      {
        case X86EMU_MEMIO_8:
          outb(addr, *val);
          break;
        case X86EMU_MEMIO_16:
          outw(addr, *val);
          break;
        case X86EMU_MEMIO_32:
          outl(addr, *val);
          break;
      }
      break;
  }

  return 0;
}


Code:
    x86emu_t* emu = x86emu_new(X86EMU_PERM_RWX, X86EMU_PERM_RWX);

    x86emu_set_memio_handler(emu, (x86emu_memio_handler_t*) alternate_vm_memio);

    x86emu_set_seg_register(emu, emu->x86.R_CS_SEL, 0);
    emu->x86.R_IP = 0x7C00;

    mem_write_word(0x7C00, 0x10CD);
    mem_write_byte(0x7C02, 0xF4);

    emu->x86.R_AX = 0x4F02;
    emu->x86.R_BX = 0x117;
   
    x86emu_run(emu, X86EMU_RUN_LOOP);

    dprintf(3, "AX: %x\n", emu->x86.R_AX);


Thanks, everything is great now!

Author:  Agola [ Fri Mar 03, 2017 1:01 pm ]
Post subject:  Re: Question about libx86emu

Yes, I was marked thread as 'Solved', but I had a new question and I didn't want to open a new thread for it.

Does libx86emu has PIC emulation? If not, as I remapped PICs, interrupts uses PICs will be confused.
I couldn't find anything about PIC in source.

Can I reset the PIC before the interrupt, and restore its state after interrupt? But then it's going to be a hacky code, and it is going to look like "Napalm's Protected Mode BIOS Functionality" which I didn't want to use before because that also resets PICs.

Thanks in advance.

Author:  Korona [ Fri Mar 03, 2017 3:37 pm ]
Post subject:  Re: Question about libx86emu

As far as I understand the library only emulates the instruction set. You have to handle (e.g. save/restore or emulate) the PIC yourself using the I/O handler.

Page 1 of 2 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/