OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 1:02 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Question about libx86emu
PostPosted: Sun Feb 26, 2017 11:20 am 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
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.

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Last edited by Agola on Fri Mar 03, 2017 12:51 pm, edited 2 times in total.

Top
 Profile  
 
 Post subject: Re: I can't find libx86emu or x86emu
PostPosted: Sun Feb 26, 2017 11:31 am 
Offline
Member
Member
User avatar

Joined: Mon Jul 18, 2016 2:46 pm
Posts: 170
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)


Top
 Profile  
 
 Post subject: Re: I can't find libx86emu or x86emu
PostPosted: Sun Feb 26, 2017 12:56 pm 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
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.

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Top
 Profile  
 
 Post subject: Re: I can't find libx86emu or x86emu
PostPosted: Sun Feb 26, 2017 2:17 pm 
Offline
Member
Member

Joined: Sat Mar 01, 2014 2:59 pm
Posts: 1146
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.

_________________
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.

Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing


Top
 Profile  
 
 Post subject: Re: I can't find libx86emu or x86emu
PostPosted: Sun Feb 26, 2017 2:25 pm 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
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.

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Top
 Profile  
 
 Post subject: Re: I can't find libx86emu or x86emu
PostPosted: Sun Feb 26, 2017 4:16 pm 
Offline
Member
Member
User avatar

Joined: Mon Jul 18, 2016 2:46 pm
Posts: 170
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/


Top
 Profile  
 
 Post subject: Re: I can't find libx86emu or x86emu
PostPosted: Sun Feb 26, 2017 4:55 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5100
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.


Top
 Profile  
 
 Post subject: Re: I can't find libx86emu or x86emu
PostPosted: Sun Feb 26, 2017 7:22 pm 
Offline
Member
Member
User avatar

Joined: Sun Dec 25, 2016 1:54 am
Posts: 204
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

_________________
Plagiarize. Plagiarize. Let not one line escape thine eyes...


Top
 Profile  
 
 Post subject: Re: I can't find libx86emu or x86emu
PostPosted: Mon Feb 27, 2017 9:16 am 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
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.

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Top
 Profile  
 
 Post subject: Re: I can't find libx86emu or x86emu
PostPosted: Mon Feb 27, 2017 10:04 am 
Offline
Member
Member

Joined: Thu May 17, 2007 1:27 pm
Posts: 999
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.

_________________
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].


Top
 Profile  
 
 Post subject: Re: I can't find libx86emu or x86emu
PostPosted: Mon Feb 27, 2017 11:05 am 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
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.

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Top
 Profile  
 
 Post subject: Re: I can't find libx86emu or x86emu
PostPosted: Mon Feb 27, 2017 11:43 am 
Offline
Member
Member
User avatar

Joined: Sun Dec 25, 2016 1:54 am
Posts: 204
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...

_________________
Plagiarize. Plagiarize. Let not one line escape thine eyes...


Top
 Profile  
 
 Post subject: Re: I can't find libx86emu or x86emu
PostPosted: Mon Feb 27, 2017 1:35 pm 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
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!

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Top
 Profile  
 
 Post subject: Re: Question about libx86emu
PostPosted: Fri Mar 03, 2017 1:01 pm 
Offline
Member
Member
User avatar

Joined: Sun Nov 20, 2016 7:26 am
Posts: 155
Location: Somewhere
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.

_________________
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.


Top
 Profile  
 
 Post subject: Re: Question about libx86emu
PostPosted: Fri Mar 03, 2017 3:37 pm 
Offline
Member
Member

Joined: Thu May 17, 2007 1:27 pm
Posts: 999
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.

_________________
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 56 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group