diff options
Diffstat (limited to 'tools/firmware/hvmloader/util.c')
-rw-r--r-- | tools/firmware/hvmloader/util.c | 591 |
1 files changed, 461 insertions, 130 deletions
diff --git a/tools/firmware/hvmloader/util.c b/tools/firmware/hvmloader/util.c index 2ce5367fb9..79c9578d13 100644 --- a/tools/firmware/hvmloader/util.c +++ b/tools/firmware/hvmloader/util.c @@ -18,160 +18,196 @@ * Place - Suite 330, Boston, MA 02111-1307 USA. */ -#include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */ +#include "acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */ #include "util.h" +#include "config.h" #include <stdint.h> +#include <xenctrl.h> +#include <xen/hvm/hvm_info_table.h> + +void outb(uint16_t addr, uint8_t val) +{ + __asm__ __volatile__ ( "outb %%al, %%dx" :: "d"(addr), "a"(val) ); +} void outw(uint16_t addr, uint16_t val) { - __asm__ __volatile__ ("outw %%ax, %%dx" :: "d"(addr), "a"(val)); + __asm__ __volatile__ ( "outw %%ax, %%dx" :: "d"(addr), "a"(val) ); } -void outb(uint16_t addr, uint8_t val) +void outl(uint16_t addr, uint32_t val) { - __asm__ __volatile__ ("outb %%al, %%dx" :: "d"(addr), "a"(val)); + __asm__ __volatile__ ( "outl %%eax, %%dx" :: "d"(addr), "a"(val) ); } uint8_t inb(uint16_t addr) { - uint8_t val; - __asm__ __volatile__ ("inb %w1,%0" : "=a" (val) : "Nd" (addr)); - return val; + uint8_t val; + __asm__ __volatile__ ( "inb %%dx,%%al" : "=a" (val) : "d" (addr) ); + return val; +} + +uint16_t inw(uint16_t addr) +{ + uint16_t val; + __asm__ __volatile__ ( "inw %%dx,%%ax" : "=a" (val) : "d" (addr) ); + return val; +} + +uint32_t inl(uint16_t addr) +{ + uint32_t val; + __asm__ __volatile__ ( "inl %%dx,%%eax" : "=a" (val) : "d" (addr) ); + return val; } char *itoa(char *a, unsigned int i) { - unsigned int _i = i, x = 0; + unsigned int _i = i, x = 0; - do { - x++; - _i /= 10; - } while (_i != 0); + do { + x++; + _i /= 10; + } while ( _i != 0 ); - a += x; - *a-- = '\0'; + a += x; + *a-- = '\0'; - do { - *a-- = (i % 10) + '0'; - i /= 10; - } while (i != 0); + do { + *a-- = (i % 10) + '0'; + i /= 10; + } while ( i != 0 ); - return a + 1; + return a + 1; } int strcmp(const char *cs, const char *ct) { - signed char res; + signed char res; - while (((res = *cs - *ct++) == 0) && (*cs++ != '\0')) - continue; + while ( ((res = *cs - *ct++) == 0) && (*cs++ != '\0') ) + continue; - return res; + return res; } void *memcpy(void *dest, const void *src, unsigned n) { - int t0, t1, t2; - - __asm__ __volatile__( - "cld\n" - "rep; movsl\n" - "testb $2,%b4\n" - "je 1f\n" - "movsw\n" - "1: testb $1,%b4\n" - "je 2f\n" - "movsb\n" - "2:" - : "=&c" (t0), "=&D" (t1), "=&S" (t2) - : "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src) - : "memory" - ); - return dest; + int t0, t1, t2; + + __asm__ __volatile__ ( + "cld\n" + "rep; movsl\n" + "testb $2,%b4\n" + "je 1f\n" + "movsw\n" + "1: testb $1,%b4\n" + "je 2f\n" + "movsb\n" + "2:" + : "=&c" (t0), "=&D" (t1), "=&S" (t2) + : "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src) + : "memory" ); + return dest; } -void puts(const char *s) +void *memmove(void *dest, const void *src, unsigned n) { - while (*s) - outb(0xE9, *s++); + if ( (long)dest > (long)src ) + { + n--; + while ( n > 0 ) + { + ((char *)dest)[n] = ((char *)src)[n]; + n--; + } + } + else + { + memcpy(dest, src, n); + } + return dest; } char * strcpy(char *dest, const char *src) { - char *p = dest; - while (*src) - *p++ = *src++; - *p = 0; - return dest; + char *p = dest; + while ( *src ) + *p++ = *src++; + *p = 0; + return dest; } char * strncpy(char *dest, const char *src, unsigned n) { - int i = 0; - char *p = dest; - - /* write non-NUL characters from src into dest until we run - out of room in dest or encounter a NUL in src */ - while (i < n && *src) { - *p++ = *src++; - ++i; - } - - /* pad remaining bytes of dest with NUL bytes */ - while (i < n) { - *p++ = 0; - ++i; - } - - return dest; + int i = 0; + char *p = dest; + + /* write non-NUL characters from src into dest until we run + out of room in dest or encounter a NUL in src */ + while ( (i < n) && *src ) + { + *p++ = *src++; + i++; + } + + /* pad remaining bytes of dest with NUL bytes */ + while ( i < n ) + { + *p++ = 0; + i++; + } + + return dest; } unsigned strlen(const char *s) { - int i = 0; - while (*s++) - ++i; - return i; + int i = 0; + while ( *s++ ) + i++; + return i; } void * memset(void *s, int c, unsigned n) { - uint8_t b = (uint8_t) c; - uint8_t *p = (uint8_t *)s; - int i; - for (i = 0; i < n; ++i) - *p++ = b; - return s; + uint8_t b = (uint8_t) c; + uint8_t *p = (uint8_t *)s; + int i; + for ( i = 0; i < n; i++ ) + *p++ = b; + return s; } int memcmp(const void *s1, const void *s2, unsigned n) { - unsigned i; - uint8_t *p1 = (uint8_t *) s1; - uint8_t *p2 = (uint8_t *) s2; - - for (i = 0; i < n; ++i) { - if (p1[i] < p2[i]) - return -1; - else if (p1[i] > p2[i]) - return 1; - } - - return 0; + unsigned i; + uint8_t *p1 = (uint8_t *) s1; + uint8_t *p2 = (uint8_t *) s2; + + for ( i = 0; i < n; i++ ) + { + if ( p1[i] < p2[i] ) + return -1; + else if ( p1[i] > p2[i] ) + return 1; + } + + return 0; } void cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { - __asm__ __volatile__( - "cpuid" - : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) - : "0" (idx) ); + __asm__ __volatile__ ( + "cpuid" + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) + : "0" (idx) ); } /* Write a two-character hex representation of 'byte' to digits[]. @@ -179,18 +215,18 @@ cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) void byte_to_hex(char *digits, uint8_t byte) { - uint8_t nybbel = byte >> 4; - - if (nybbel > 9) - digits[0] = 'a' + nybbel-10; - else - digits[0] = '0' + nybbel; - - nybbel = byte & 0x0f; - if (nybbel > 9) - digits[1] = 'a' + nybbel-10; - else - digits[1] = '0' + nybbel; + uint8_t nybbel = byte >> 4; + + if ( nybbel > 9 ) + digits[0] = 'a' + nybbel-10; + else + digits[0] = '0' + nybbel; + + nybbel = byte & 0x0f; + if ( nybbel > 9 ) + digits[1] = 'a' + nybbel-10; + else + digits[1] = '0' + nybbel; } /* Convert an array of 16 unsigned bytes to a DCE/OSF formatted UUID @@ -200,31 +236,326 @@ byte_to_hex(char *digits, uint8_t byte) void uuid_to_string(char *dest, uint8_t *uuid) { - int i = 0; - char *p = dest; - - for (i = 0; i < 4; ++i) { - byte_to_hex(p, uuid[i]); - p += 2; - } - *p++ = '-'; - for (i = 4; i < 6; ++i) { - byte_to_hex(p, uuid[i]); - p += 2; - } - *p++ = '-'; - for (i = 6; i < 8; ++i) { - byte_to_hex(p, uuid[i]); - p += 2; - } - *p++ = '-'; - for (i = 8; i < 10; ++i) { - byte_to_hex(p, uuid[i]); - p += 2; - } - *p++ = '-'; - for (i = 10; i < 16; ++i) { - byte_to_hex(p, uuid[i]); - p += 2; - } + int i = 0; + char *p = dest; + + for ( i = 0; i < 4; i++ ) + { + byte_to_hex(p, uuid[i]); + p += 2; + } + *p++ = '-'; + for ( i = 4; i < 6; i++ ) + { + byte_to_hex(p, uuid[i]); + p += 2; + } + *p++ = '-'; + for ( i = 6; i < 8; i++ ) + { + byte_to_hex(p, uuid[i]); + p += 2; + } + *p++ = '-'; + for ( i = 8; i < 10; i++ ) + { + byte_to_hex(p, uuid[i]); + p += 2; + } + *p++ = '-'; + for ( i = 10; i < 16; i++ ) + { + byte_to_hex(p, uuid[i]); + p += 2; + } + *p = '\0'; +} + +#include <xen/hvm/e820.h> +#define E820_MAP_NR ((unsigned char *)E820_MAP_PAGE + E820_MAP_NR_OFFSET) +#define E820_MAP ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET)) +uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask) +{ + uint64_t addr = 0; + int c = *E820_MAP_NR - 1; + struct e820entry *e820entry = (struct e820entry *)E820_MAP; + + while ( c >= 0 ) + { + if ( (e820entry[c].type == E820_RAM) && + ((e820entry[c].addr & (~mask)) == 0) && + (e820entry[c].size >= size) ) + { + addr = e820entry[c].addr; + if ( e820entry[c].size != size ) + { + (*E820_MAP_NR)++; + memmove(&e820entry[c+1], + &e820entry[c], + (*E820_MAP_NR - c) * + sizeof(struct e820entry)); + e820entry[c].size -= size; + addr += e820entry[c].size; + c++; + } + e820entry[c].addr = addr; + e820entry[c].size = size; + e820entry[c].type = type; + break; + } + c--; + } + return addr; +} + +uint32_t ioapic_read(uint32_t reg) +{ + *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00) = reg; + return *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10); +} + +void ioapic_write(uint32_t reg, uint32_t val) +{ + *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00) = reg; + *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10) = val; +} + +uint32_t lapic_read(uint32_t reg) +{ + return *(volatile uint32_t *)(LAPIC_BASE_ADDRESS + reg); +} + +void lapic_write(uint32_t reg, uint32_t val) +{ + *(volatile uint32_t *)(LAPIC_BASE_ADDRESS + reg) = val; +} + +#define PCI_CONF1_ADDRESS(bus, devfn, reg) \ + (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3)) + +uint32_t pci_read(uint32_t devfn, uint32_t reg, uint32_t len) +{ + outl(0xcf8, PCI_CONF1_ADDRESS(0, devfn, reg)); + + switch ( len ) + { + case 1: return inb(0xcfc + (reg & 3)); + case 2: return inw(0xcfc + (reg & 2)); + } + + return inl(0xcfc); +} + +void pci_write(uint32_t devfn, uint32_t reg, uint32_t len, uint32_t val) +{ + outl(0xcf8, PCI_CONF1_ADDRESS(0, devfn, reg)); + + switch ( len ) + { + case 1: outb(0xcfc + (reg & 3), val); break; + case 2: outw(0xcfc + (reg & 2), val); break; + case 4: outl(0xcfc, val); break; + } +} + +static char *printnum(char *p, unsigned long num, int base) +{ + unsigned long n; + + if ( (n = num/base) > 0 ) + p = printnum(p, n, base); + *p++ = "0123456789abcdef"[(int)(num % base)]; + *p = '\0'; + return p; +} + +static void _doprint(void (*put)(char), char const *fmt, va_list ap) +{ + register char *str, c; + int lflag, zflag, nflag; + char buffer[17]; + unsigned value; + int i, slen, pad; + + for ( ; *fmt != '\0'; fmt++ ) + { + if ( *fmt != '%' ) + { + put(*fmt); + continue; + } + + pad = zflag = nflag = lflag = 0; + c = *++fmt; + if ( (c == '-') || isdigit(c) ) + { + if ( c == '-' ) + { + nflag = 1; + c = *++fmt; + } + zflag = c == '0'; + for ( pad = 0; isdigit(c); c = *++fmt ) + pad = (pad * 10) + c - '0'; + } + if ( c == 'l' ) /* long extension */ + { + lflag = 1; + c = *++fmt; + } + if ( (c == 'd') || (c == 'u') || (c == 'o') || (c == 'x') ) + { + if ( lflag ) + value = va_arg(ap, unsigned); + else + value = (unsigned) va_arg(ap, unsigned int); + str = buffer; + printnum(str, value, + c == 'o' ? 8 : (c == 'x' ? 16 : 10)); + goto printn; + } + else if ( (c == 'O') || (c == 'D') || (c == 'X') ) + { + value = va_arg(ap, unsigned); + str = buffer; + printnum(str, value, + c == 'O' ? 8 : (c == 'X' ? 16 : 10)); + printn: + slen = strlen(str); + for ( i = pad - slen; i > 0; i-- ) + put(zflag ? '0' : ' '); + while ( *str ) + put(*str++); + } + else if ( c == 's' ) + { + str = va_arg(ap, char *); + slen = strlen(str); + if ( nflag == 0 ) + for ( i = pad - slen; i > 0; i-- ) + put(' '); + while ( *str ) + put(*str++); + if ( nflag ) + for ( i = pad - slen; i > 0; i-- ) + put(' '); + } + else if ( c == 'c' ) + { + put(va_arg(ap, int)); + } + else + { + put(*fmt); + } + } +} + +static void putchar(char c) +{ + outb(0xe9, c); } + +int printf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _doprint(putchar, fmt, ap); + va_end(ap); + + return 0; +} + +int vprintf(const char *fmt, va_list ap) +{ + _doprint(putchar, fmt, ap); + return 0; +} + +void __assert_failed(char *assertion, char *file, int line) +{ + printf("HVMLoader assertion '%s' failed at %s:%d\n", + assertion, file, line); + for ( ; ; ) + __asm__ __volatile__ ( "ud2" ); +} + +void __bug(char *file, int line) +{ + printf("HVMLoader bug at %s:%d\n", file, line); + for ( ; ; ) + __asm__ __volatile__ ( "ud2" ); +} + +static int validate_hvm_info(struct hvm_info_table *t) +{ + char signature[] = "HVM INFO"; + uint8_t *ptr = (uint8_t *)t; + uint8_t sum = 0; + int i; + + /* strncmp(t->signature, "HVM INFO", 8) */ + for ( i = 0; i < 8; i++ ) + { + if ( signature[i] != t->signature[i] ) + { + printf("Bad hvm info signature\n"); + return 0; + } + } + + for ( i = 0; i < t->length; i++ ) + sum += ptr[i]; + + return (sum == 0); +} + +static struct hvm_info_table *get_hvm_info_table(void) +{ + static struct hvm_info_table *table; + struct hvm_info_table *t; + + if ( table != NULL ) + return table; + + t = (struct hvm_info_table *)HVM_INFO_PADDR; + + if ( !validate_hvm_info(t) ) + { + printf("Bad hvm info table\n"); + return NULL; + } + + table = t; + + return table; +} + +int get_vcpu_nr(void) +{ + struct hvm_info_table *t = get_hvm_info_table(); + return (t ? t->nr_vcpus : 1); +} + +int get_acpi_enabled(void) +{ + struct hvm_info_table *t = get_hvm_info_table(); + return (t ? t->acpi_enabled : 1); +} + +int get_apic_mode(void) +{ + struct hvm_info_table *t = get_hvm_info_table(); + return (t ? t->apic_mode : 1); +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ |