# 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
|