diff -r e66cecb66b1e tools/firmware/hvmloader/smbios.c --- a/tools/firmware/hvmloader/smbios.c Wed Oct 08 14:00:58 2008 +0100 +++ b/tools/firmware/hvmloader/smbios.c Thu Oct 09 09:18:03 2008 -0600 @@ -56,11 +56,11 @@ static void * static void * smbios_type_16_init(void *start, uint32_t memory_size_mb); static void * -smbios_type_17_init(void *start, uint32_t memory_size_mb); +smbios_type_17_init(void *start, uint32_t memory_size_mb, int instance); static void * -smbios_type_19_init(void *start, uint32_t memory_size_mb); +smbios_type_19_init(void *start, uint32_t memory_size_mb, int instance); static void * -smbios_type_20_init(void *start, uint32_t memory_size_mb); +smbios_type_20_init(void *start, uint32_t memory_size_mb, int instance); static void * smbios_type_32_init(void *start); static void * @@ -89,9 +89,11 @@ write_smbios_tables(void *start, uint8_t uuid[16], char *xen_version, uint32_t xen_major_version, uint32_t xen_minor_version) { + uint64_t devmemsize; unsigned cpu_num, nr_structs = 0, max_struct_size = 0; char *p, *q; char cpu_manufacturer[15]; + int i; get_cpu_manufacturer(cpu_manufacturer, 15); @@ -112,9 +114,15 @@ write_smbios_tables(void *start, for ( cpu_num = 1; cpu_num <= vcpus; cpu_num++ ) do_struct(smbios_type_4_init(p, cpu_num, cpu_manufacturer)); do_struct(smbios_type_16_init(p, memsize)); - do_struct(smbios_type_17_init(p, memsize)); - do_struct(smbios_type_19_init(p, memsize)); - do_struct(smbios_type_20_init(p, memsize)); + for ( i=0; memsize; memsize -= devmemsize ) + { + devmemsize = (memsize < 0x4000) ? memsize : 0x4000; + /* more than 1 of each type needed if memsize */ + /* represents greater than 16G */ + do_struct(smbios_type_17_init(p, devmemsize,i)); + do_struct(smbios_type_19_init(p, devmemsize,i)); + do_struct(smbios_type_20_init(p, devmemsize,i++)); + } do_struct(smbios_type_32_init(p)); do_struct(smbios_type_127_init(p)); @@ -456,7 +464,8 @@ smbios_type_16_init(void *start, uint32_ p->error_correction = 0x01; /* other */ p->maximum_capacity = memsize * 1024; p->memory_error_information_handle = 0xfffe; /* none provided */ - p->number_of_memory_devices = 1; + p->number_of_memory_devices = ( memsize <= 0x4000 )?1: + ( memsize % 0x4000 )? (memsize >> 14)+1:memsize >> 14; start += sizeof(struct smbios_type_16); *((uint16_t *)start) = 0; @@ -465,15 +474,16 @@ smbios_type_16_init(void *start, uint32_ /* Type 17 -- Memory Device */ static void * -smbios_type_17_init(void *start, uint32_t memory_size_mb) +smbios_type_17_init(void *start, uint32_t memory_size_mb, int instance) { + char buf[16]; struct smbios_type_17 *p = (struct smbios_type_17 *)start; memset(p, 0, sizeof(*p)); p->header.type = 17; p->header.length = sizeof(struct smbios_type_17); - p->header.handle = 0x1100; + p->header.handle = 0x1100+instance; p->physical_memory_array_handle = 0x1000; p->total_width = 64; @@ -489,8 +499,11 @@ smbios_type_17_init(void *start, uint32_ p->type_detail = 0; start += sizeof(struct smbios_type_17); - strcpy((char *)start, "DIMM 1"); - start += strlen("DIMM 1") + 1; + strcpy((char *)start, "DIMM "); + start += strlen("DIMM "); + itoa(buf, instance); + strcpy((char *)start, buf); + start += strlen(buf) +1; *((uint8_t *)start) = 0; return start+1; @@ -498,7 +511,7 @@ smbios_type_17_init(void *start, uint32_ /* Type 19 -- Memory Array Mapped Address */ static void * -smbios_type_19_init(void *start, uint32_t memory_size_mb) +smbios_type_19_init(void *start, uint32_t memory_size_mb, int instance) { struct smbios_type_19 *p = (struct smbios_type_19 *)start; @@ -506,10 +519,10 @@ smbios_type_19_init(void *start, uint32_ p->header.type = 19; p->header.length = sizeof(struct smbios_type_19); - p->header.handle = 0x1300; + p->header.handle = 0x1300+instance; - p->starting_address = 0; - p->ending_address = (memory_size_mb-1) * 1024; + p->starting_address = instance*0x4000; + p->ending_address = (( memory_size_mb+instance*0x4000 )-1)* 1024; p->memory_array_handle = 0x1000; p->partition_width = 1; @@ -528,11 +541,11 @@ smbios_type_20_init(void *start, uint32_ p->header.type = 20; p->header.length = sizeof(struct smbios_type_20); - p->header.handle = 0x1400; + p->header.handle = 0x1400+instance; - p->starting_address = 0; - p->ending_address = (memory_size_mb-1)*1024; - p->memory_device_handle = 0x1100; + p->starting_address = instance*0x4000; + p->ending_address = (( memory_size_mb+instance*0x4000 ) -1)*1024; + p->memory_device_handle = 0x1100+instance; p->memory_array_mapped_address_handle = 0x1300; p->partition_row_position = 1; p->interleave_position = 0;