[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] General hvmloader cleanups and write memory fields of CMOS with



# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1174088064 0
# Node ID cf32c9e54c8f44e45fcab47bc98c37e181f93771
# Parent  519d32076d48317f798c6670ca32c9bdabc14d10
General hvmloader cleanups and write memory fields of CMOS with
correct values.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 tools/firmware/hvmloader/32bitbios_support.c |  118 ++++++++++++---------------
 tools/firmware/hvmloader/acpi/build.c        |    1 
 tools/firmware/hvmloader/hvmloader.c         |   67 +++++++++++----
 tools/firmware/hvmloader/smbios.c            |   48 +++-------
 tools/firmware/hvmloader/util.c              |   21 +++-
 tools/firmware/hvmloader/util.h              |   10 ++
 6 files changed, 144 insertions(+), 121 deletions(-)

diff -r 519d32076d48 -r cf32c9e54c8f 
tools/firmware/hvmloader/32bitbios_support.c
--- a/tools/firmware/hvmloader/32bitbios_support.c      Fri Mar 16 23:33:44 
2007 +0000
+++ b/tools/firmware/hvmloader/32bitbios_support.c      Fri Mar 16 23:34:24 
2007 +0000
@@ -17,58 +17,64 @@
  * 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 *e
                     break;
                 }
             }
-        } else if (shdr[i].sh_type == SHT_RELA) {
-            return -2;
         }
     }
     return 0;
 }
 
-/* scan the rombios for the destination of the jumptable */
-static char* get_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) )
+            break;
+
+    if ( i == ehdr->e_shnum )
+    {
+        printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n");
+        return -4;
     }
 
-     /* 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);
-                }
-            }
-            break;
-        }
-    }
-
-    if (biosjumptable == NULL) {
-        printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n");
-        rc = -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;
+    char *highbiosarea;
+    int rc;
 
-    highbiosarea = (unsigned char *)(long)
-                           e820_malloc((uint64_t)to_malloc,
-                                       E820_RESERVED,
-                                       (uint64_t)0xffffffff);
+    highbiosarea = (char *)(long)
+        e820_malloc((elfarraysize + mask) & ~mask, /* round to 64kb */
+                    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;
-    }
+    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));
 }
diff -r 519d32076d48 -r cf32c9e54c8f tools/firmware/hvmloader/acpi/build.c
--- a/tools/firmware/hvmloader/acpi/build.c     Fri Mar 16 23:33:44 2007 +0000
+++ b/tools/firmware/hvmloader/acpi/build.c     Fri Mar 16 23:34:24 2007 +0000
@@ -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))
diff -r 519d32076d48 -r cf32c9e54c8f tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c      Fri Mar 16 23:33:44 2007 +0000
+++ b/tools/firmware/hvmloader/hvmloader.c      Fri Mar 16 23:34:24 2007 +0000
@@ -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. */
+/*
+ * 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) 
+{
     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 ) 
+    /* 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;
-    /* Read CMOS register 0x38 (boot choice 2 and FDD test flag) */
-    outb(0x70, 0x38);
-    boot_order = inb(0x71);
-    if ( (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)
@@ -365,6 +396,8 @@ int main(void)
         acpi_sz = acpi_build_tables((uint8_t *)ACPI_PHYSICAL_ADDRESS);
         ASSERT((ACPI_PHYSICAL_ADDRESS + acpi_sz) <= 0xF0000);
     }
+
+    cmos_write_memory_size();
 
     if ( !check_amd() )
     {
diff -r 519d32076d48 -r cf32c9e54c8f tools/firmware/hvmloader/smbios.c
--- a/tools/firmware/hvmloader/smbios.c Fri Mar 16 23:33:44 2007 +0000
+++ b/tools/firmware/hvmloader/smbios.c Fri Mar 16 23:34:24 2007 +0000
@@ -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
diff -r 519d32076d48 -r cf32c9e54c8f tools/firmware/hvmloader/util.c
--- a/tools/firmware/hvmloader/util.c   Fri Mar 16 23:33:44 2007 +0000
+++ b/tools/firmware/hvmloader/util.c   Fri Mar 16 23:34:24 2007 +0000
@@ -27,17 +27,17 @@
 
 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)
@@ -59,6 +59,18 @@ uint32_t inl(uint16_t addr)
     uint32_t val;
     __asm__ __volatile__ ( "inl %%dx,%%eax" : "=a" (val) : "d" (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)
@@ -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;
diff -r 519d32076d48 -r cf32c9e54c8f tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h   Fri Mar 16 23:33:44 2007 +0000
+++ b/tools/firmware/hvmloader/util.h   Fri Mar 16 23:34:24 2007 +0000
@@ -25,6 +25,10 @@ uint8_t  inb(uint16_t addr);
 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);
@@ -78,9 +82,13 @@ 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')
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.