]> xenbits.xensource.com Git - xen.git/commitdiff
General hvmloader cleanups and write memory fields of CMOS with
authorKeir Fraser <keir@xensource.com>
Fri, 16 Mar 2007 23:34:24 +0000 (23:34 +0000)
committerKeir Fraser <keir@xensource.com>
Fri, 16 Mar 2007 23:34:24 +0000 (23:34 +0000)
correct values.
Signed-off-by: Keir Fraser <keir@xensource.com>
tools/firmware/hvmloader/32bitbios_support.c
tools/firmware/hvmloader/acpi/build.c
tools/firmware/hvmloader/hvmloader.c
tools/firmware/hvmloader/smbios.c
tools/firmware/hvmloader/util.c
tools/firmware/hvmloader/util.h

index bfde19577fcb156ba7e41a39fe74369822029642..e835037d969954ab76396f8aa9f4d8dbb232a669 100644 (file)
  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  * Place - Suite 330, Boston, MA 02111-1307 USA.
  */
+
 #include <inttypes.h>
 #include <elf.h>
 #ifdef __sun__
 #include <sys/machelf.h>
 #endif
 
-#include <xen/hvm/e820.h>
 #include "util.h"
 #include "config.h"
 
 #include "../rombios/32bit/32bitbios_flat.h"
 #include "../rombios/32bit/jumptable.h"
 
-
-/*
- * relocate ELF file of type ET_REL
- */
-static int relocate_elf(unsigned char *elfarray) {
+/* Relocate ELF file of type ET_REL */
+static int relocate_elf(char *elfarray)
+{
     Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray;
     Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff];
     int i;
 
-    if (ehdr->e_type != ET_REL) {
+    if ( ehdr->e_type != ET_REL )
+    {
         printf("Not a relocatable BIOS object file. Has type %d, need %d\n",
                ehdr->e_type, ET_REL);
         return -1;
     }
 
-    for (i = 0; i < ehdr->e_shnum; i++)
+    for ( i = 0; i < ehdr->e_shnum; i++ )
         shdr[i].sh_addr = (Elf32_Addr)&elfarray[shdr[i].sh_offset];
 
-    for (i = 0; i < ehdr->e_shnum; i++) {
-        if (shdr[i].sh_type == SHT_REL) {
+    for ( i = 0; i < ehdr->e_shnum; i++ )
+    {
+        if ( shdr[i].sh_type == SHT_RELA )
+            return -2;
+
+        if ( shdr[i].sh_type == SHT_REL )
+        {
             Elf32_Shdr *targetsec = (Elf32_Shdr *)&(shdr[shdr[i].sh_info]);
             Elf32_Shdr *symtabsec = (Elf32_Shdr *)&(shdr[shdr[i].sh_link]);
             Elf32_Sym  *syms      = (Elf32_Sym *)symtabsec->sh_addr;
             Elf32_Rel  *rels      = (Elf32_Rel *)shdr[i].sh_addr;
-            unsigned char *code   = (unsigned char *)targetsec->sh_addr;
+            char *code            = (char *)targetsec->sh_addr;
             int j;
 
             /* must not have been stripped */
-            if (shdr[i].sh_size == 0)
+            if ( shdr[i].sh_size == 0 )
                 return -6;
 
-            for (j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++) {
+            for ( j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++ )
+            {
                 int idx           = ELF32_R_SYM(rels[j].r_info);
                 Elf32_Sym *symbol = &syms[idx];
                 uint32_t *loc     = (uint32_t *)&code[rels[j].r_offset];
                 uint32_t fix      = shdr[symbol->st_shndx].sh_addr +
                                     symbol->st_value;
 
-                switch (ELF32_R_TYPE(rels[j].r_info)) {
+                switch ( ELF32_R_TYPE(rels[j].r_info) )
+                {
                     case R_386_PC32:
                         *loc += (fix - (uint32_t)loc);
                     break;
@@ -78,96 +84,80 @@ static int relocate_elf(unsigned char *elfarray) {
                     break;
                 }
             }
-        } else if (shdr[i].sh_type == SHT_RELA) {
-            return -2;
         }
     }
     return 0;
 }
 
-/* scan the rombios for the destination of the jumptable */
-static charget_jump_table_start(void)
+/* Scan the rombios for the destination of the jump table. */
+static char *get_jump_table_start(void)
 {
     char *bios_mem;
 
     for ( bios_mem = (char *)ROMBIOS_BEGIN;
           bios_mem != (char *)ROMBIOS_END;
-          bios_mem++ ) {
-        if (strncmp(bios_mem, "___JMPT", 7) == 0)
+          bios_mem++ )
+    {
+        if ( strncmp(bios_mem, "___JMPT", 7) == 0 )
             return bios_mem;
     }
 
     return NULL;
 }
 
-/* copy relocated jumptable into the rombios */
-static int copy_jumptable(unsigned char *elfarray)
+/* Copy relocated jumptable into the rombios. */
+static int copy_jumptable(char *elfarray)
 {
-    int rc = 0;
     Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray;
     Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff];
     Elf32_Shdr *shdr_strings = (Elf32_Shdr *)&shdr[ehdr->e_shstrndx];
     char *secstrings = (char *)&elfarray[shdr_strings->sh_offset];
     uint32_t *rombiosjumptable = (uint32_t *)get_jump_table_start();
-    uint32_t *biosjumptable    = NULL;
     int i;
 
-    if (rombiosjumptable == NULL) {
+    if ( rombiosjumptable == NULL )
         return -3;
-    }
 
-     /* find the section with the jump table  and copy to lower BIOS memory */
-    for (i = 0; i < ehdr->e_shnum; i++) {
-        if (!strcmp(JUMPTABLE_SECTION_NAME, secstrings + shdr[i].sh_name)) {
-            uint32_t biosjumptableentries;
-            biosjumptable        = (uint32_t *)shdr[i].sh_addr;
-            biosjumptableentries = shdr[i].sh_size / 4;
-            for (int j = 0; j < biosjumptableentries; j++) {
-                rombiosjumptable[j] = biosjumptable[j];
-                if (biosjumptable[j] == 0 &&
-                    j < (biosjumptableentries - 1)) {
-                    printf("WARNING: jumptable entry %d is NULL!\n",j);
-                }
-            }
+    /* Find the section with the jump table and copy to lower BIOS memory. */
+    for ( i = 0; i < ehdr->e_shnum; i++ )
+        if ( !strcmp(JUMPTABLE_SECTION_NAME, secstrings + shdr[i].sh_name) )
             break;
-        }
-    }
 
-    if (biosjumptable == NULL) {
+    if ( i == ehdr->e_shnum )
+    {
         printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n");
-        rc = -4;
+        return -4;
     }
 
+    memcpy(rombiosjumptable, (uint32_t *)shdr[i].sh_addr, shdr[i].sh_size);
+
     return 0;
 }
 
-static int relocate_32bitbios(unsigned char *elfarray, uint32_t elfarraysize)
+static int relocate_32bitbios(char *elfarray, uint32_t elfarraysize)
 {
-    int rc = 0;
     uint32_t mask = (64 * 1024) - 1;
-    uint32_t to_malloc = (elfarraysize + mask) & ~mask; /* round to 64kb */
-    unsigned char *highbiosarea;
-
-    highbiosarea = (unsigned char *)(long)
-                           e820_malloc((uint64_t)to_malloc,
-                                       E820_RESERVED,
-                                       (uint64_t)0xffffffff);
-
-    if (highbiosarea != 0) {
-        memcpy(highbiosarea, elfarray, elfarraysize);
-        rc = relocate_elf(highbiosarea);
-        if (rc == 0) {
-            rc = copy_jumptable(highbiosarea);
-        }
-    } else {
-        rc = -5;
-    }
+    char *highbiosarea;
+    int rc;
+
+    highbiosarea = (char *)(long)
+        e820_malloc((elfarraysize + mask) & ~mask, /* round to 64kb */
+                    E820_RESERVED,
+                    (uint64_t)0xffffffff);
+
+    if ( highbiosarea == NULL )
+        return -5;
+
+    memcpy(highbiosarea, elfarray, elfarraysize);
+    rc = relocate_elf(highbiosarea);
+    if ( rc == 0 )
+        rc = copy_jumptable(highbiosarea);
 
     return rc;
 }
 
 int highbios_setup(void)
 {
-    return relocate_32bitbios((unsigned char *)highbios_array,
+    return relocate_32bitbios((char *)highbios_array,
                               sizeof(highbios_array));
 }
index 3db71cabfeb38132e21ef3e8b6a55579b4e9965a..7be1ea4a715544e8bac7da7ffa713615889fb1d2 100644 (file)
@@ -20,7 +20,6 @@
 #include "ssdt_tpm.h"
 #include "../config.h"
 #include "../util.h"
-#include <xen/hvm/e820.h>
 
 #define align16(sz)        (((sz) + 15) & ~15)
 #define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d))
index 8bed54835a87d5f90157735d536f23eeb83c186c..beabd06248897f82bff67819517a6306ea8d9c1a 100644 (file)
@@ -29,7 +29,6 @@
 #include "pci_regs.h"
 #include <xen/version.h>
 #include <xen/hvm/params.h>
-#include <xen/hvm/e820.h>
 
 /* memory map */
 #define HYPERCALL_PHYSICAL_ADDRESS    0x00080000
@@ -297,25 +296,57 @@ static void pci_setup(void)
     }
 }
 
-static 
-int must_load_nic(void) 
+/*
+ * If the network card is in the boot order, load the Etherboot option ROM.
+ * Read the boot order bytes from CMOS and check if any of them are 0x4.
+ */
+static int must_load_nic(void) 
 {
-    /* If the network card is in the boot order, load the Etherboot 
-     * option ROM.  Read the boot order bytes from CMOS and check 
-     * if any of them are 0x4. */
     uint8_t boot_order;
 
-    /* Read CMOS register 0x3d (boot choices 0 and 1) */
-    outb(0x70, 0x3d);
-    boot_order = inb(0x71);
-    if ( (boot_order & 0xf) == 0x4 || (boot_order & 0xf0) == 0x40 ) 
-        return 1;
-    /* Read CMOS register 0x38 (boot choice 2 and FDD test flag) */
-    outb(0x70, 0x38);
-    boot_order = inb(0x71);
-    if ( (boot_order & 0xf0) == 0x40 ) 
+    /* Read CMOS register 0x3d (boot choices 0 and 1). */
+    boot_order = cmos_inb(0x3d);
+    if ( ((boot_order & 0xf) == 0x4) || ((boot_order & 0xf0) == 0x40) ) 
         return 1;
-    return 0;
+
+    /* Read CMOS register 0x38 (boot choice 2 and FDD test flag). */
+    boot_order = cmos_inb(0x38);
+    return ((boot_order & 0xf0) == 0x40);
+}
+
+/* Replace possibly erroneous memory-size CMOS fields with correct values. */
+static void cmos_write_memory_size(void)
+{
+    struct e820entry *map = E820_MAP;
+    int i, nr = *E820_MAP_NR;
+    uint32_t base_mem = 640, ext_mem = 0, alt_mem = 0;
+
+    for ( i = 0; i < nr; i++ )
+        if ( (map[i].addr >= 0x100000) && (map[i].type == E820_RAM) )
+            break;
+
+    if ( i != nr )
+    {
+        alt_mem = ext_mem = map[i].addr + map[i].size;
+        ext_mem = (ext_mem > 0x0100000) ? (ext_mem - 0x0100000) >> 10 : 0;
+        if ( ext_mem > 0xffff )
+            ext_mem = 0xffff;
+        alt_mem = (alt_mem > 0x1000000) ? (alt_mem - 0x1000000) >> 16 : 0;
+    }
+
+    /* All BIOSes: conventional memory (640kB). */
+    cmos_outb(0x15, (uint8_t)(base_mem >> 0));
+    cmos_outb(0x16, (uint8_t)(base_mem >> 8));
+
+    /* All BIOSes: extended memory (1kB chunks above 1MB). */
+    cmos_outb(0x17, (uint8_t)( ext_mem >> 0));
+    cmos_outb(0x18, (uint8_t)( ext_mem >> 8));
+    cmos_outb(0x30, (uint8_t)( ext_mem >> 0));
+    cmos_outb(0x31, (uint8_t)( ext_mem >> 8));
+
+    /* Some BIOSes: alternative extended memory (64kB chunks above 16MB). */
+    cmos_outb(0x34, (uint8_t)( alt_mem >> 0));
+    cmos_outb(0x35, (uint8_t)( alt_mem >> 8));
 }
 
 int main(void)
@@ -366,6 +397,8 @@ int main(void)
         ASSERT((ACPI_PHYSICAL_ADDRESS + acpi_sz) <= 0xF0000);
     }
 
+    cmos_write_memory_size();
+
     if ( !check_amd() )
     {
         printf("Loading VMXAssist ...\n");
index df25999c3a18799cb2a4447cad96916b59fb10be..c9a4992e4c3fdd66e9a204fbd39bda63cfbc1914 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <stdint.h>
 #include <xen/version.h>
-#include <xen/hvm/e820.h>
 #include "smbios.h"
 #include "smbios_types.h"
 #include "util.h"
@@ -129,47 +128,32 @@ write_smbios_tables(void *start,
     return (size_t)((char *)p - (char *)start);
 }
 
-/* This tries to figure out how much pseudo-physical memory (in MB)
-   is allocated to the current domU.
-
-   It iterates through the e820 table, adding up the 'usable' and
-   'reserved' entries and rounding up to the nearest MB.
-
-   The e820map is not at e820 in hvmloader, so this uses the
-   E820_MAP_* constants from e820.h to pick it up where libxenguest
-   left it.
- */
+/* Calculate how much pseudo-physical memory (in MB) is allocated to us. */
 static uint64_t
 get_memsize(void)
 {
-    struct e820entry *map = NULL;
-    uint8_t num_entries = 0;
+    struct e820entry *map = E820_MAP;
+    uint8_t num_entries = *E820_MAP_NR;
     uint64_t memsize = 0;
-    uint8_t i;
-
-    map = (struct e820entry *) (E820_MAP_PAGE + E820_MAP_OFFSET);
-    num_entries = *((uint8_t *) (E820_MAP_PAGE + E820_MAP_NR_OFFSET));
-
-    /* walk through e820map, ignoring any entries that aren't marked
-       as usable or reserved. */
+    int i;
 
+    /*
+     * Walk through e820map, ignoring any entries that aren't marked
+     * as usable or reserved.
+     */
     for ( i = 0; i < num_entries; i++ )
     {
-        if (map->type == E820_RAM || map->type == E820_RESERVED)
+        if ( (map->type == E820_RAM) || (map->type == E820_RESERVED) )
             memsize += map->size;
         map++;
     }
 
-    /* Round up to the nearest MB.  The user specifies domU
-       pseudo-physical memory in megabytes, so not doing this
-       could easily lead to reporting one less MB than the user
-       specified. */
-    if ( memsize & ((1<<20)-1) )
-        memsize = (memsize >> 20) + 1;
-    else
-        memsize = (memsize >> 20);
-
-    return memsize;
+    /*
+     * Round up to the nearest MB.  The user specifies domU pseudo-physical 
+     * memory in megabytes, so not doing this could easily lead to reporting 
+     * one less MB than the user specified.
+     */
+    return (memsize + (1 << 20) - 1) >> 20;
 }
 
 void
index ce32a9001e913ab11dab69d38f011ed62f1437d7..2f5f23d1e5e63358dd831d00140f0c07dcab33a5 100644 (file)
 
 void outb(uint16_t addr, uint8_t val)
 {
-    __asm__ __volatile__ ( "outb %%al, %%dx" :: "d"(addr), "a"(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 outl(uint16_t addr, uint32_t val)
 {
-    __asm__ __volatile__ ( "outl %%eax, %%dx" :: "d"(addr), "a"(val) );
+    __asm__ __volatile__ ( "outl %%eax, %%dx" : : "d" (addr), "a" (val) );
 }
 
 uint8_t inb(uint16_t addr)
@@ -61,6 +61,18 @@ uint32_t inl(uint16_t addr)
     return val;
 }
 
+uint8_t cmos_inb(uint8_t idx)
+{
+    outb(0x70, idx);
+    return inb(0x71);
+}
+
+void cmos_outb(uint8_t idx, uint8_t val)
+{
+    outb(0x70, idx);
+    outb(0x71, val);
+}
+
 char *itoa(char *a, unsigned int i)
 {
     unsigned int _i = i, x = 0;
@@ -280,9 +292,6 @@ uuid_to_string(char *dest, uint8_t *uuid)
     *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;
index 368f93ddda0559acdd9eeb799539fda3d7371dfd..5025748437dea18167713b4da9ef1a501d19da3f 100644 (file)
@@ -26,6 +26,10 @@ uint8_t  inb(uint16_t addr);
 uint16_t inw(uint16_t addr);
 uint32_t inl(uint16_t addr);
 
+/* CMOS access */
+uint8_t cmos_inb(uint8_t idx);
+void cmos_outb(uint8_t idx, uint8_t val);
+
 /* APIC access */
 uint32_t ioapic_read(uint32_t reg);
 void ioapic_write(uint32_t reg, uint32_t val);
@@ -78,10 +82,14 @@ int vprintf(const char *fmt, va_list ap);
 /* Allocate region of specified type in the e820 table. */
 uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask);
 
+/* General e820 access. */
+#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))
+
 /* Prepare the 32bit BIOS */
 int highbios_setup(void);
 
-
 #define isdigit(c) ((c) >= '0' && (c) <= '9')
 
 #endif /* __HVMLOADER_UTIL_H__ */