diff options
-rwxr-xr-x | kvm/bios/rombios32.c | 70 |
1 files changed, 45 insertions, 25 deletions
diff --git a/kvm/bios/rombios32.c b/kvm/bios/rombios32.c index a91b15562..3c9a2d7d8 100755 --- a/kvm/bios/rombios32.c +++ b/kvm/bios/rombios32.c @@ -370,6 +370,17 @@ int vsnprintf(char *buf, int buflen, const char *fmt, va_list args) return buf - buf0; } +int snprintf(char * buf, size_t size, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=vsnprintf(buf,size,fmt,args); + va_end(args); + return i; +} + void bios_printf(int flags, const char *fmt, ...) { va_list ap; @@ -1914,7 +1925,7 @@ smbios_type_4_init(void *start, unsigned int cpu_number) /* Type 16 -- Physical Memory Array */ static void * -smbios_type_16_init(void *start, uint32_t memsize) +smbios_type_16_init(void *start, uint32_t memsize, int nr_mem_devs) { struct smbios_type_16 *p = (struct smbios_type_16*)start; @@ -1927,7 +1938,7 @@ smbios_type_16_init(void *start, uint32_t memsize) 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 = nr_mem_devs; start += sizeof(struct smbios_type_16); *((uint16_t *)start) = 0; @@ -1937,20 +1948,19 @@ smbios_type_16_init(void *start, uint32_t memsize) /* 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) { struct smbios_type_17 *p = (struct smbios_type_17 *)start; 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; p->data_width = 64; - /* truncate memory_size_mb to 16 bits and clear most significant - bit [indicates size in MB] */ - p->size = (uint16_t) memory_size_mb & 0x7fff; +/* TODO: should assert in case something is wrong ASSERT((memory_size_mb & ~0x7fff) == 0); */ + p->size = memory_size_mb; p->form_factor = 0x09; /* DIMM */ p->device_set = 0; p->device_locator_str = 1; @@ -1959,8 +1969,8 @@ smbios_type_17_init(void *start, uint32_t memory_size_mb) p->type_detail = 0; start += sizeof(struct smbios_type_17); - memcpy((char *)start, "DIMM 1", 7); - start += 7; + snprintf(start, 8, "DIMM %d", instance); + start += strlen(start) + 1; *((uint8_t *)start) = 0; return start+1; @@ -1968,16 +1978,16 @@ smbios_type_17_init(void *start, uint32_t memory_size_mb) /* 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; 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 * 1024) - 1; + p->starting_address = instance << 24; + p->ending_address = p->starting_address + (memory_size_mb << 10) - 1; p->memory_array_handle = 0x1000; p->partition_width = 1; @@ -1989,18 +1999,18 @@ smbios_type_19_init(void *start, uint32_t memory_size_mb) /* Type 20 -- Memory Device Mapped Address */ 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) { struct smbios_type_20 *p = (struct smbios_type_20 *)start; 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 * 1024) - 1; - p->memory_device_handle = 0x1100; - p->memory_array_mapped_address_handle = 0x1300; + p->starting_address = instance << 24; + p->ending_address = p->starting_address + (memory_size_mb << 10) - 1; + p->memory_device_handle = 0x1100 + instance; + p->memory_array_mapped_address_handle = 0x1300 + instance; p->partition_row_position = 1; p->interleave_position = 0; p->interleaved_data_depth = 0; @@ -2051,6 +2061,7 @@ void smbios_init(void) char *start, *p, *q; int memsize = (ram_end == ram_size) ? ram_size / (1024 * 1024) : (ram_end - (1ull << 32) + ram_size) / (1024 * 1024); + int i, nr_mem_devs; #ifdef BX_USE_EBDA_TABLES ebda_cur_addr = align(ebda_cur_addr, 16); @@ -2062,23 +2073,32 @@ void smbios_init(void) p = (char *)start + sizeof(struct smbios_entry_point); -#define add_struct(fn) { \ +#define add_struct(fn) do{ \ q = (fn); \ nr_structs++; \ if ((q - p) > max_struct_size) \ max_struct_size = q - p; \ p = q; \ -} +}while (0) add_struct(smbios_type_0_init(p)); add_struct(smbios_type_1_init(p)); add_struct(smbios_type_3_init(p)); for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++) add_struct(smbios_type_4_init(p, cpu_num)); - add_struct(smbios_type_16_init(p, memsize)); - add_struct(smbios_type_17_init(p, memsize)); - add_struct(smbios_type_19_init(p, ram_end / (1024 * 1024))); - add_struct(smbios_type_20_init(p, ram_end / (1024 * 1024))); + + /* Each 'memory device' covers up to 16GB of address space. */ + nr_mem_devs = (memsize + 0x3fff) >> 14; + add_struct(smbios_type_16_init(p, memsize, nr_mem_devs)); + for ( i = 0; i < nr_mem_devs; i++ ) + { + uint32_t dev_memsize = ((i == (nr_mem_devs - 1)) + ? (memsize & 0x3fff) : 0x4000); + add_struct(smbios_type_17_init(p, dev_memsize, i)); + add_struct(smbios_type_19_init(p, dev_memsize, i)); + add_struct(smbios_type_20_init(p, dev_memsize, i)); + } + add_struct(smbios_type_32_init(p)); add_struct(smbios_type_127_init(p)); |