diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2015-05-20 16:03:33 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-05-21 11:44:57 +0200 |
commit | edba90fb16ec7224da591ab8f83efe3673853a3f (patch) | |
tree | 61b37be2e6e96a2163878e2df98e1f638ce5590e /e820.c | |
parent | d092feedb023a3d631a1cd549dd1d5c18d852ac7 (diff) | |
download | qboot-edba90fb16ec7224da591ab8f83efe3673853a3f.zip qboot-edba90fb16ec7224da591ab8f83efe3673853a3f.tar.gz qboot-edba90fb16ec7224da591ab8f83efe3673853a3f.tar.bz2 |
first commit
Based on x86/bios from lkvm
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'e820.c')
-rw-r--r-- | e820.c | 70 |
1 files changed, 70 insertions, 0 deletions
@@ -0,0 +1,70 @@ +#include "bios.h" +#include "segment.h" + +#include "processor-flags.h" +#include "e820.h" + +static inline void set_fs(uint16_t seg) +{ + asm volatile("movw %0,%%fs" : : "rm" (seg)); +} + +static inline uint8_t rdfs8(unsigned long addr) +{ + uint8_t v; + + asm volatile("addr32 movb %%fs:%1,%0" : "=q" (v) : "m" (*(uint8_t *)addr)); + + return v; +} + +static inline uint32_t rdfs32(unsigned long addr) +{ + uint32_t v; + + asm volatile("addr32 movl %%fs:%1,%0" : "=q" (v) : "m" (*(uint32_t *)addr)); + + return v; +} + +bioscall void e820_query_map(struct biosregs *regs) +{ + struct e820map *e820; + uint32_t map_size; + uint16_t fs_seg; + uint32_t ndx; + + e820 = (struct e820map *)E820_MAP_START; + fs_seg = flat_to_seg16(E820_MAP_START); + set_fs(fs_seg); + + ndx = regs->ebx; + + map_size = rdfs32(flat_to_off16((uint32_t)&e820->nr_map, fs_seg)); + + if (ndx < map_size) { + uint32_t start; + unsigned int i; + uint8_t *p; + + fs_seg = flat_to_seg16(E820_MAP_START); + set_fs(fs_seg); + + start = (uint32_t)&e820->map[ndx]; + + p = (void *) regs->edi; + + for (i = 0; i < sizeof(struct e820entry); i++) + *p++ = rdfs8(flat_to_off16(start + i, fs_seg)); + } + + regs->eax = SMAP; + regs->ecx = sizeof(struct e820entry); + regs->ebx = ++ndx; + + /* Clear CF to indicate success. */ + regs->eflags &= ~X86_EFLAGS_CF; + + if (ndx >= map_size) + regs->ebx = 0; /* end of map */ +} |